Skip to content

Instantly share code, notes, and snippets.

@kaspth
Created July 13, 2024 21:33
Show Gist options
  • Save kaspth/5241c6ee1e1a1ee18a335e67c7ce411f to your computer and use it in GitHub Desktop.
Save kaspth/5241c6ee1e1a1ee18a335e67c7ce411f to your computer and use it in GitHub Desktop.
require "bundler/inline"
gemfile do
gem "activerecord", require: "active_record"
gem "pg"
end
ActiveRecord::Base.logger = Logger.new STDOUT
begin
ActiveRecord::Tasks::DatabaseTasks.drop(adapter: "postgresql", database: "kanban_boards")
ActiveRecord::Tasks::DatabaseTasks.create(adapter: "postgresql", database: "kanban_boards")
end
ActiveRecord::Base.establish_connection adapter: "postgresql", database: "kanban_boards"
ActiveRecord::Schema.define do
create_table :kanban_stages do |t|
t.string :title, null: false
t.integer :placements_positions, null: false, array: true, default: []
end
create_table :kanban_stage_placements do |t|
t.string :title, null: false
t.references :stage, null: false, index: true
end
end
# Played around with a general abstraction for this way, but didn't get very far with it.
class ActiveRecord::Positioned < ActiveRecord::Base
belongs_to :record, polymorphic: true
# name
# position_ids, :integer, array: true
# def ordered = record.public_send(name).in_order_of(:id, position_ids)
end
module Kanban; def self.table_name_prefix = "kanban_"; end
class Kanban::Stage < ActiveRecord::Base
has_many :placements do
# Mostly for debugging.
def positioned = in_order_of(:id, proxy_association.owner.placements_positions)
end
def place(placement, after: nil) = transaction do
placement.update! stage: self
index = index(after)&.succ || 0
update! placements_positions: placements_positions.insert(index, placement.id).uniq
end
def index(placement) = placements_positions.index(placement.id)
end
class Kanban::Stage::Placement < ActiveRecord::Base
belongs_to :stage
end
todo = Kanban::Stage.create! title: "To-do"
3.times { todo.place todo.placements.create! title: "Procrastinating #{_1}" }
p todo.placements.positioned
doing = Kanban::Stage.create! title: "Doing"
doing.place doing.placements.create! title: "Bike Shedding"
doing.place todo.placements.second, after: doing.placements.last # Simulate a drag'n'drop onto the last placement
p doing.placements.positioned
binding.irb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment