ActiveScaffold Kanban
ActiveScaffold Kanban renders scaffold records as cards grouped into board columns. Moving a card to another board column updates the configured model attribute or association, and optional sortable integration persists the order of cards within each column.
Requirements
- Active Scaffold 3.7.11 or newer
- ActiveScaffold Sortable 3.2.2 or newer
- ActiveScaffold Config List 3.6.0 or newer
Sortable and Config List are runtime dependencies and are installed with the Kanban gem. Their actions are enabled per scaffold only when their corresponding features are needed.
Installation
Add the following line to your Gemfile:
gem 'active_scaffold_kanban'Then run:
bundle installBasic configuration
Enable :kanban and select the database column or association used to group the cards:
class TasksController < ApplicationController
active_scaffold :task do |config|
config.actions << :kanban
config.kanban.group_by_column = :status
end
endOpen the index with ?view=kanban to display the board. To make the board the scaffold’s default index view instead, set:
config.kanban.replace_list_view = truePagination is disabled while rendering the Kanban view so that all records in the current result set can be placed on the board.
Board columns
The kanban_columns helper returns the available board columns as [label, value] pairs. By default it resolves values in the same way as a column using the :select form UI:
- For a regular model column, set
config.columns[:status].options[:options]or overrideactive_scaffold_enum_options. - For an association, use
options_for_association_conditionsorassociation_klass_scopedto restrict the available associated records. The association column’slabel_methodcontrols their labels.
These helper overrides support the model-name prefix. You can also replace the complete board-column list:
module TasksHelper
def task_kanban_columns
[['Backlog', 'backlog'], ['In progress', 'started'], ['Done', 'done']]
end
endFor an association, the second item in each pair must be the associated record rather than its ID.
Moving and ordering cards
Dragging a card to another board column calls Active Scaffold’s update_column action to update group_by_column, using the same save and authorization path as in-place editing. If the update fails, the request returns an error and the card moves back to its original position.
Cross-column moves work without enabling the :sortable action, but card order is not persisted. Reordering within the same board column is disabled, and the apparent position of a card moved to another column may change when the board reloads.
To persist card order, enable Sortable and configure its position column:
active_scaffold :task do |config|
config.actions << :kanban
config.kanban.group_by_column = :status
config.actions << :sortable
config.sortable.column = :position
endWith this configuration, a move within one board column calls the Sortable reorder action. A move between columns updates the grouping value through update_column and then persists the submitted order.
Receive-only columns
A board column can accept cards while preventing its existing cards from being dragged out. Override kanban_column_receive_only?; it receives the board-column value, which is the associated record when group_by_column is an association:
module TasksHelper
def task_kanban_column_receive_only?(status)
status == 'done'
end
endThis helper also supports the model-name prefix, as shown above.
Config List integration
When the scaffold also enables :config_list, users can choose which board columns are visible and arrange their order:
config.actions << :config_listKanban column preferences are stored separately from the ordinary list-column configuration. List sorting settings are not applied to board columns.
Card content and actions
Configure the model methods used for card content:
config.kanban.title_method = :name # default: :to_label
config.kanban.description_method = :summaryNo description content is shown by default. To customize only the description markup, override kanban_description(record) or its model-prefixed form, such as task_kanban_description(record).
To replace the complete card markup, override _kanban_card.html.erb in the controller’s view directory, for example app/views/tasks/_kanban_card.html.erb.
Cards render the scaffold’s normal member action links. Inline links whose normal position is :before, :after, or :replace use config.kanban.links_position, which defaults to :table, while the board is active. An action link can be hidden from the board by assigning an ignore_method that checks @kanban_view, or by overriding skip_action_link?.
The normal create action also works from the Kanban view. After a successful create, the new card is inserted into the board column matching its group_by_column value.
Global defaults
The title method, description method, default-view behavior, and link position can be configured for every Kanban scaffold before controller configurations are built:
ActiveScaffold::Config::Kanban.title_method = :name
ActiveScaffold::Config::Kanban.description_method = :summary
ActiveScaffold::Config::Kanban.replace_list_view = true
ActiveScaffold::Config::Kanban.links_position = :tablegroup_by_column must still be configured for each scaffold.
JavaScript hook
Before a card moves to a different board column, the plugin fires kanban:beforeChange on the card. The handler receives an object containing id (the record ID) and column (the destination value, or the associated record ID for an association).
Return false to reject the move. Extra parameters placed in the card’s params data are merged into the update_column request:
$(document).on('kanban:beforeChange', '.kanban .card', function(event, data) {
if (data.column === 'done' && !window.confirm('Mark this task as done?')) {
return false;
}
$(this).data('params', { changed_from: 'kanban' });
});