summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-16 22:34:51 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-16 22:40:55 +0200
commitfc4c03cdc3a7c68fe764581287b6b13d92b440fc (patch)
treea942c7a1ad6ef459cd1423733eaa7c7f6ec952bc
parentc831c46b5522a44cefd430bdca04ec9db5a90052 (diff)
Add a script to backfill action log from existing records
-rw-r--r--lib/tasks/node_actions.rake61
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/tasks/node_actions.rake b/lib/tasks/node_actions.rake
new file mode 100644
index 0000000..fdd286c
--- /dev/null
+++ b/lib/tasks/node_actions.rake
@@ -0,0 +1,61 @@
1namespace :node_actions do
2 desc "Rebuild inferred NodeAction entries from existing revisions and " \
3 "node timestamps. Witnessed entries (inferred_from IS NULL) are " \
4 "never touched; previously inferred ones are deleted and " \
5 "regenerated, so the task is idempotent. Scope with NODE_ID=n."
6 task :backfill => :environment do
7 scope = Node.where.not(:parent_id => nil)
8 scope = scope.where(:id => ENV["NODE_ID"]) if ENV["NODE_ID"]
9
10 created = 0
11
12 ActiveRecord::Base.transaction do
13 stale = NodeAction.where.not(:inferred_from => nil)
14 stale = stale.where(:node_id => ENV["NODE_ID"]) if ENV["NODE_ID"]
15 puts "Removing #{stale.count} previously inferred entries"
16 stale.delete_all
17
18 witnessed_creates = NodeAction.where(:action => "create", :inferred_from => nil).pluck(:node_id).to_set
19 witnessed_promotes = NodeAction.where(:action => "publish", :inferred_from => nil).pluck(:page_id).to_set
20
21 scope.find_each do |node|
22 # Every page row except the current draft was once promoted to
23 # head. Autosaves never carry node_id, so they cannot appear.
24 revisions = node.pages.to_a.reject { |page| page.id == node.draft_id }
25 first_page = node.pages.first
26
27 unless witnessed_creates.include?(node.id)
28 NodeAction.record!(
29 :node => node, :page => first_page, :user => first_page&.editor,
30 :action => "create",
31 :occurred_at => node.created_at,
32 :inferred_from => "from_node_created_at",
33 :title => first_page&.translations&.find_by(:locale => I18n.default_locale)&.title,
34 :path => node.unique_name,
35 :human_readable_node_name =>
36 first_page&.translations&.find_by(:locale => I18n.default_locale)&.title)
37 created += 1
38 end
39
40 previous = nil
41 revisions.each do |page|
42 unless witnessed_promotes.include?(page.id)
43 diff = NodeAction.head_diff(previous, page)
44 NodeAction.record!(
45 :node => node, :page => page, :user => page.editor,
46 :action => "publish",
47 :occurred_at => page.updated_at,
48 :inferred_from => "from_page_revision",
49 :via => "draft",
50 :human_readable_node_name => diff[:title]["to"],
51 **diff)
52 created += 1
53 end
54 previous = page
55 end
56 end
57 end
58
59 puts "Created #{created} inferred entries"
60 end
61end