Commit a780fe59 authored by charlie ablett's avatar charlie ablett

Create EpicBoardPosition class

- with RelativePositioning
- with scope
parent ab6a20b5
---
title: Add Epic Board Position model to store relative positioning of epics on a board
merge_request: 48120
author:
type: added
# frozen_string_literal: true
class AddEpicBoardPositions < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
with_lock_retries do
create_table :epic_board_positions do |t|
t.references :board, foreign_key: { on_delete: :cascade }, null: false, index: false
t.references :epic, foreign_key: { on_delete: :cascade }, null: false, index: true
t.integer :relative_position
t.timestamps_with_timezone null: false
t.index [:board_id, :epic_id], unique: true, name: :index_epic_board_positions_on_board_id_and_epic_id
end
end
end
def down
drop_table :epic_board_positions
end
end
a3c26d7c88080d5d914d2d4ee0abd80d3d6c51739708d88b42a1c976f9510ee8
\ No newline at end of file
# frozen_string_literal: true
module EE
module EpicBoardPosition
extend ActiveSupport::Concern
prepended do
include RelativePositioning
belongs_to :board
belongs_to :epic
validates :board, presence: true
validates :epic, presence: true, uniqueness: { scope: :board_id }
alias_attribute :parent, :board
scope :order_relative_position, -> do
reorder('relative_position ASC', 'id DESC')
end
end
class_methods do
extend ::Gitlab::Utils::Override
def relative_positioning_query_base(position)
where(board_id: position.board_id)
end
def relative_positioning_parent_column
:board_id
end
end
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :epic_board_position do
epic
board
relative_position { RelativePositioning::START_POSITION }
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe EpicBoardPosition do
let_it_be(:epic) { create(:epic) }
let_it_be(:group) { create(:group) }
let_it_be(:board) { create(:board, group: group) }
let_it_be(:epic_board_position) { create(:epic_board_position, epic: epic, board: board) }
describe 'associations' do
subject { build(:epic_board_position) }
it { is_expected.to belong_to(:epic) }
it { is_expected.to belong_to(:board) }
end
describe 'validations' do
subject { build(:epic_board_position) }
it { is_expected.to validate_presence_of(:epic) }
it { is_expected.to validate_presence_of(:board) }
specify { expect(subject).to be_valid }
it 'is valid with nil relative position' do
subject.relative_position = nil
expect(subject).to be_valid
end
it 'disallows a record with same epic and board' do
expect(build(:epic_board_position, epic: epic, board: board)).not_to be_valid
end
end
describe 'scopes' do
describe '.order_relative_position' do
let(:first) { epic_board_position }
let!(:second) { create(:epic_board_position, board: board, relative_position: RelativePositioning::START_POSITION + 7 ) }
it 'returns epic_board_positions in order' do
expect(described_class.order_relative_position).to eq([first, second])
end
end
end
context 'relative positioning' do
let_it_be(:positioning_group) { create(:group) }
let_it_be(:positioning_board) { create(:board, group: positioning_group) }
it_behaves_like "a class that supports relative positioning" do
let(:factory) { :epic_board_position }
let(:default_params) { { parent: positioning_board } }
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment