diff --git a/db/migrations/014_bingo_updated_at.rb b/db/migrations/014_bingo_updated_at.rb
new file mode 100644
index 0000000..2df7048
--- /dev/null
+++ b/db/migrations/014_bingo_updated_at.rb
@@ -0,0 +1,13 @@
+Sequel.migration do
+ up do
+ # Last change to the row, for the "updated" date and sitemap lastmod.
+ %i[bingo_datacenters bingo_incidents].each do |t|
+ add_column t, :updated_at, DateTime
+ from(t).update(updated_at: :created_at)
+ end
+ end
+
+ down do
+ %i[bingo_datacenters bingo_incidents].each { |t| drop_column t, :updated_at }
+ end
+end
diff --git a/lib/bingo.rb b/lib/bingo.rb
index b1fb328..707e96c 100644
--- a/lib/bingo.rb
+++ b/lib/bingo.rb
@@ -99,6 +99,11 @@ module Bingo
super
end
+ def before_save
+ self.updated_at = Time.now.utc
+ super
+ end
+
def operational? = status == 'operational'
def planned? = status == 'planned'
@@ -126,10 +131,21 @@ module Bingo
include Localized
many_to_one :datacenter, class: 'Bingo::Datacenter'
+ # A removed incident changes its datacenter's cell.
+ def after_destroy
+ super
+ Datacenter.where(id: datacenter_id).update(updated_at: Time.now.utc)
+ end
+
def before_create
self.created_at ||= Time.now.utc
super
end
+
+ def before_save
+ self.updated_at = Time.now.utc
+ super
+ end
end
# Board state for rendering: ordered cells, hits and completed lines.
@@ -145,7 +161,7 @@ module Bingo
hit = cells.map { |dc| dc.incidents.any? }
wins = LINES.select { |line| line.all? { |i| hit[i] } }
incidents = cells.flat_map(&:incidents).sort_by { |i| [i.occurred_on, i.id] }.reverse
- updated = [Datacenter.max(:created_at), Incident.max(:created_at)].compact.max
+ updated = [Datacenter.max(:updated_at), Incident.max(:updated_at)].compact.max
new(cells, hit, wins, incidents, updated, view)
end
@@ -364,7 +380,10 @@ module Bingo
end
def self.renumber!(ids = Datacenter.order(:position, :id).select_map(:id))
- ids.each_with_index { |id, i| Datacenter.where(id: id).update(position: i + 1) }
+ now = Time.now.utc
+ ids.each_with_index do |id, i|
+ Datacenter.where(id: id).exclude(position: i + 1).update(position: i + 1, updated_at: now)
+ end
end
# "64" → 64.0, "25–30" → 30.0, ">40" → 40.0, "13,7" → 13.7, "" → nil
@@ -388,14 +407,14 @@ module Bingo
path = File.join($root, 'db', 'bingo_seed.json')
return unless File.exist?(path)
seed = JSON.parse(File.read(path, encoding: 'UTF-8'))
- cols = Datacenter.columns.map(&:to_s) - %w[id created_at]
+ cols = Datacenter.columns.map(&:to_s) - %w[id created_at updated_at]
DB.connection.transaction do
ids = seed.fetch('datacenters').each_with_index.to_h do |row, i|
dc = Datacenter.create(row.slice(*cols).merge('position' => row['position'] || i + 1))
[dc.slug, dc.id]
end
seed.fetch('incidents', []).each do |row|
- Incident.create(row.slice(*(Incident.columns.map(&:to_s) - %w[id created_at datacenter_id]))
+ Incident.create(row.slice(*(Incident.columns.map(&:to_s) - %w[id created_at updated_at datacenter_id]))
.merge('datacenter_id' => ids.fetch(row.fetch('slug'))))
end
end
diff --git a/lib/bingo_admin.rb b/lib/bingo_admin.rb
index ac443a8..e010bbe 100644
--- a/lib/bingo_admin.rb
+++ b/lib/bingo_admin.rb
@@ -221,7 +221,7 @@ module BingoAdmin
app.post '/admin/bingo/incidents/:id/delete' do
inc = Bingo::Incident[params[:id].to_i]
- Bingo::Incident.where(id: params[:id].to_i).delete
+ inc&.destroy # hook bumps the datacenter's updated_at
audit!('bingo.incident_delete', inc&.datacenter&.slug, inc && "#{inc.occurred_on} #{inc.title_ru}")
session[:bingo_flash] = 'Incident deleted.'
redirect '/admin/bingo'
diff --git a/test/bingo_test.rb b/test/bingo_test.rb
index 9d6ab31..22a97e8 100644
--- a/test/bingo_test.rb
+++ b/test/bingo_test.rb
@@ -175,6 +175,21 @@ class BingoTest < Minitest::Test
assert last_response.ok?
%w[ru en uk].each { |l| assert_includes last_response.body, "https://example.org/#{l}" }
assert_includes last_response.body, 'hreflang="x-default"'
+ refute_includes last_response.body, 'changefreq'
+ assert_match %r{\n \d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ\n , old
+ DB.connection[:bingo_datacenters].update(updated_at: old)
+ inc = hit!(2)
+ DB.connection[:bingo_incidents].update(created_at: old, updated_at: old)
+ inc.refresh.destroy
+ assert_operator Bingo::Board.load.updated_on, :>, old
end
def test_asxpio_static_files_not_served
diff --git a/views/bingo/sitemap.erb b/views/bingo/sitemap.erb
index 6267d6e..fe49fef 100644
--- a/views/bingo/sitemap.erb
+++ b/views/bingo/sitemap.erb
@@ -3,8 +3,8 @@
<% Bingo::LOCALES.each do |l| %>
<%= base_url %>/<%= l %>
-<% if @lastmod %> <%= @lastmod.utc.strftime('%Y-%m-%d') %>
-<% end %> daily
+<% if @lastmod %> <%= @lastmod.utc.iso8601 %>
+<% end %>
<% Bingo::LOCALES.each do |alt| %>
<% end %>