Skip to content

Commit

Permalink
Add reset! method to trending petition journal
Browse files Browse the repository at this point in the history
  • Loading branch information
cih committed Apr 2, 2017
1 parent 315606f commit d00436c
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
7 changes: 7 additions & 0 deletions app/models/signature.rb
Expand Up @@ -114,6 +114,13 @@ def self.trending_ips(since: 1.hour.ago, limit: 20)
count(:all)
end

def self.validated_dates
validated.
where.not(validated_at: nil).
order("date").
pluck("DISTINCT date(validated_at) as date")
end

scope :in_days, ->(number_of_days) { validated.where("updated_at > ?", number_of_days.day.ago) }
scope :matching, ->(signature) { where(email: signature.email,
name: signature.name,
Expand Down
24 changes: 24 additions & 0 deletions app/models/trending_petition_journal.rb
Expand Up @@ -34,6 +34,30 @@ def invalidate_signature_for(signature, now = Time.current)
end
end

def reset!
connection.execute "TRUNCATE TABLE trending_petition_journals"

Petition.find_each do |petition|
petition.signatures.validated_dates.each do |date|
journal = self.for(petition, date)

journal.with_lock do
updates = petition
.signatures
.validated
.select("count(petition_id), EXTRACT(hour from validated_at) as hour")
.where("date(validated_at) = ?", date)
.group("hour")
.each_with_object({}) do |interval, updates|
updates["hour_#{interval.hour.to_i}_signature_count"] = interval.count
end

journal.update_columns(updates.merge(updated_at: Time.current))
end
end
end
end

private

def unrecordable?(signature)
Expand Down
19 changes: 19 additions & 0 deletions spec/models/signature_spec.rb
Expand Up @@ -615,6 +615,25 @@
end
end

describe ".validated_dates" do
let(:now) { Time.parse("1 Jan 2017 08:30") }

around do |example|
travel_to(now) { example.run }
end

it "returns an ordered array of unique dates based on the validated at timestamp" do
FactoryGirl.create(:validated_signature, validated_at: now)
FactoryGirl.create(:validated_signature, validated_at: now)
FactoryGirl.create(:validated_signature, validated_at: now - 1.day)
FactoryGirl.create(:validated_signature, validated_at: now - 3.days)
FactoryGirl.create(:invalidated_signature, validated_at: now - 4.days)

expect(described_class.validated_dates)
.to eq [Date.parse("29 Dec 2016"), Date.parse("31 Dec 2016"), Date.parse("1 Jan 2017")]
end
end

describe "#number" do
let(:attributes) { FactoryGirl.attributes_for(:petition) }
let(:creator) { FactoryGirl.create(:pending_signature) }
Expand Down
64 changes: 64 additions & 0 deletions spec/models/trending_petition_journal_spec.rb
Expand Up @@ -210,5 +210,69 @@ def journal
end
end
end

describe ".reset!" do
let(:petition_1) { FactoryGirl.create(:petition) }
let(:petition_2) { FactoryGirl.create(:petition) }
let(:today) { Time.parse("1 Jan 2017 08:00") }
let(:two_hours_ago) { today - 2.hours }
let(:two_days_ago) { today - 2.days }

around do |example|
travel_to(today) { example.run }
end

before do
described_class.for(petition_1).update_attribute(:hour_8_signature_count, 20)
described_class.for(petition_2).update_attribute(:hour_8_signature_count, 100)
end

context "when there are no signatures" do
it "resets all the hourly counts to 0 except for 1 for the creator signature" do
described_class.reset!

expect(described_class.for(petition_1).hour_8_signature_count).to eq 1
expect(described_class.for(petition_2).hour_8_signature_count).to eq 1

[*0..7, *9..23].each do |hour|
expect(
described_class.for(petition_1)
.public_send("hour_#{hour}_signature_count")
).to eq 0

expect(
described_class.for(petition_2)
.public_send("hour_#{hour}_signature_count")
).to eq 0
end
end
end

context "when there are signatures" do
before do
2.times { FactoryGirl.create(:validated_signature, petition: petition_1, validated_at: today) }
2.times { FactoryGirl.create(:validated_signature, petition: petition_1, validated_at: two_hours_ago) }
3.times { FactoryGirl.create(:validated_signature, petition: petition_1, validated_at: two_days_ago) }
2.times { FactoryGirl.create(:pending_signature, petition: petition_1) }

1.times { FactoryGirl.create(:validated_signature, petition: petition_2, validated_at: today) }
1.times { FactoryGirl.create(:validated_signature, petition: petition_2, validated_at: two_hours_ago) }
2.times { FactoryGirl.create(:validated_signature, petition: petition_2, validated_at: two_days_ago) }
1.times { FactoryGirl.create(:pending_signature, petition: petition_2) }
end

it "resets the counts to that of the validated signatures for the petition, day and hour" do
described_class.reset!

expect(described_class.for(petition_1, today).hour_8_signature_count).to eq 3 # +1 for creator signature
expect(described_class.for(petition_1, today).hour_6_signature_count).to eq 2
expect(described_class.for(petition_1, two_days_ago).hour_8_signature_count).to eq 3

expect(described_class.for(petition_2, today).hour_8_signature_count).to eq 2 # +1 for creator signature
expect(described_class.for(petition_2, today).hour_6_signature_count).to eq 1
expect(described_class.for(petition_2, two_days_ago).hour_8_signature_count).to eq 2
end
end
end
end

0 comments on commit d00436c

Please sign in to comment.