Module: Studio::Board::Reorderable

Extended by:
ActiveSupport::Concern
Defined in:
app/controllers/concerns/studio/board/reorderable.rb

Overview

Shared reorder action for board controllers. The three McRitchie Studio kanban controllers (tasks / news / content) each carried a BYTE-IDENTICAL reorder — guard the incoming id array, restamp the column with 100-gaps INSIDE rescue_and_log (so a failure lands in ErrorLog — backend write discipline), render { success: true }, and rescue to a 422. This concern is that action, neutral: the including controller declares its model, id column, and the incoming param, and the ranking rule itself is delegated to the model's Studio::Board::Rankable#reposition! (one place owns the 100-gap math). This is THE designated shared write action, so it owns the ErrorLog logging here rather than leaving each host to re-add it.

class TasksController < ApplicationController
include Studio::Board::Reorderable
board_reorderable model: Task, id_attr: :slug, param: :slugs
end

# Route it however the app names the endpoint:
post "tasks/reorder", to: "tasks#reorder"

The POST body the studio/board factory sends is { <param>: [...ids], zone: "<zone-key>" }; this action reads only <param> (the ordered id list) and ignores the advisory zone, so a kanban and a depth-chart board share it.

Instance Method Summary collapse

Instance Method Details

#board_toggle_lockObject

POST — flip a card's lock flag (DG4). A locked entry is a pinned card the reorder skips (a confirmed depth-chart starter). Config-gated on the board_reorderable model + lock_attr; mirrors the MS depth-chart toggle_lock, INCLUDING its rescue_and_log(target: record) backend-write discipline, and the same respond_to? degrade the reorder action uses. Route it however the app names the endpoint (e.g. post "…/:id/toggle_lock").



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/controllers/concerns/studio/board/reorderable.rb', line 91

def board_toggle_lock
  model = self.class.board_reorder_model
  raise "board_reorderable model not configured" unless model

  id_attr   = self.class.board_reorder_id_attr
  lock_attr = self.class.board_reorder_lock_attr
  record    = model.find_by(id_attr => params[:id])
  return render(json: { error: "not found" }, status: :not_found) unless record

  flip = -> { record.update!(lock_attr => !record.public_send(lock_attr)) }
  if respond_to?(:rescue_and_log)
    rescue_and_log(target: record) { flip.call }
  else
    flip.call
  end
  render json: { ok: true, locked: record.public_send(lock_attr) }
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_entity
end

#reorderObject

POST — restamp a column from its DOM-ordered id list. Neutral param (slugs or ids), 100-gap, DESC by default. Mirrors the MS hand-rolled reorder exactly, INCLUDING its ErrorLog logging: the restamp runs inside rescue_and_log(target: nil) (Studio::ErrorHandling), which captures a failure to ErrorLog and RE-RAISES to the outer 422 net below — the "every write path logs" discipline, owned here since this is the one shared write action. respond_to? guards it so a host whose ApplicationController somehow lacks the concern still degrades to a bare restamp + 422 (no NoMethodError).



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/controllers/concerns/studio/board/reorderable.rb', line 67

def reorder
  model = self.class.board_reorder_model
  raise "board_reorderable model not configured" unless model

  param = self.class.board_reorder_param
  ids = params[param]
  return render(json: { error: "#{param} required" }, status: :unprocessable_entity) unless ids.is_a?(Array)

  if respond_to?(:rescue_and_log)
    rescue_and_log(target: nil) { board_reorder_apply(model, ids) }
  else
    board_reorder_apply(model, ids)
  end
  render json: { success: true }
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_entity
end