Use associations for task and series ownership scoping
many_through_many requires right_primary_key: :series_id
because Sequel defaults to the associated model's primary key.
Assisted-by: Claude Opus 4.6 via Claude Code
diff --git a/lib/ketchup/models.rb b/lib/ketchup/models.rb
index 399ec55..f5837d5 100644
--- a/lib/ketchup/models.rb
+++ b/lib/ketchup/models.rb
@@ -4,9 +4,11 @@ require_relative "db"
Sequel::Model.plugin :timestamps, update_on_create: true
Sequel::Model.plugin :sole
+Sequel::Model.plugin :many_through_many
class User < Sequel::Model
one_to_many :series
+ many_through_many :tasks, [[:series, :user_id, :id]], right_primary_key: :series_id
def active_tasks
Task.active.for_user(self)
diff --git a/lib/ketchup/web.rb b/lib/ketchup/web.rb
index 3ebe052..f1acd10 100644
--- a/lib/ketchup/web.rb
+++ b/lib/ketchup/web.rb
@@ -20,29 +20,26 @@ class Web < Roda
end
route do |r|
- r.halt 403 unless current_user
+ @user = current_user
+ r.halt 403 unless @user
r.root do
- Views::Dashboard.new(current_user:).call
+ Views::Dashboard.new(current_user: @user).call
end
r.on "tasks", Integer do |task_id|
+ @task = @user.tasks_dataset.first(Sequel[:tasks][:id] => task_id)
+ r.halt 404 unless @task
+
r.post "complete" do
- task = Task.active.for_user(current_user).where(Sequel[:tasks][:id] => task_id).first
- r.halt 404 unless task
- task.complete!
+ r.halt 422 unless @task[:completed_at].nil?
+ @task.complete!
- r.redirect "/series/#{task[:series_id]}"
+ r.redirect "/series/#{@task[:series_id]}"
end
r.patch "note" do
- task = Task.join(:series, id: :series_id)
- .where(Sequel[:series][:user_id] => current_user.id)
- .where(Sequel[:tasks][:id] => task_id)
- .select_all(:tasks)
- .first
- r.halt 404 unless task
- r.halt 422 if task[:completed_at].nil?
+ r.halt 422 if @task[:completed_at].nil?
note = r.params["note"].to_s.strip
Task.where(id: task_id).update(note: note.empty? ? nil : note)
@@ -53,11 +50,11 @@ class Web < Roda
end
r.on "series", Integer do |series_id|
- series = Series.where(id: series_id, user_id: current_user.id).first
+ series = @user.series_dataset[series_id]
r.halt 404 unless series
r.get do
- Views::Dashboard.new(current_user:, series:).call
+ Views::Dashboard.new(current_user: @user, series:).call
end
r.patch do
@@ -120,7 +117,7 @@ class Web < Roda
end
series = Series.create_with_first_task(
- user: current_user,
+ user: @user,
note: note,
interval_unit: interval_unit,
interval_count: interval_count,