Skip to content

Commit

Permalink
Support composite keys
Browse files Browse the repository at this point in the history
  • Loading branch information
jackozi committed Jul 11, 2024
1 parent 0c3be35 commit f855c01
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 8 deletions.
20 changes: 12 additions & 8 deletions lib/positioning/mechanisms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,19 @@ def primary_key_column
end

def primary_key
@positioned.send primary_key_column
if primary_key_column.is_a? Array
primary_key_column.map { |column| @positioned.send column }
else
@positioned.send primary_key_column
end
end

def quoted_column
base_class.connection.quote_table_name_for_assignment base_class.table_name, @column
end

def record_scope
base_class.where("#{primary_key_column}": primary_key)
base_class.where(Array(primary_key_column).zip(Array(primary_key)).to_h)
end

def position
Expand Down Expand Up @@ -133,12 +137,12 @@ def solidify_position
end

relative_primary_key = if relative_record_or_primary_key.is_a? base_class
relative_record_or_primary_key.send(primary_key_column)
Array(primary_key_column).map { |column| relative_record_or_primary_key.send(column) }
else
relative_record_or_primary_key
Array(relative_record_or_primary_key)
end

relative_record_scope = positioning_scope.where("#{primary_key_column}": relative_primary_key)
relative_record_scope = positioning_scope.where(Array(primary_key_column).zip(relative_primary_key).to_h)

unless relative_record_scope.exists?
raise Error.new, "relative `#{@column}` record must be in the same scope"
Expand All @@ -154,8 +158,8 @@ def solidify_position
unless position.is_a? Integer
raise Error.new,
%(`#{@column}` must be an Integer, :first, :last, ) +
%{before: (#{base_class.name}, #{primary_key_column}, nil, or ""), } +
%{after: (#{base_class.name}, #{primary_key_column}, nil or ""), nil or ""}
%{before: (#{base_class.name}, #{Array(primary_key_column).join(", ")}, nil, or ""), } +
%{after: (#{base_class.name}, #{Array(primary_key_column).join(", ")}, nil or ""), nil or ""}
end
end

Expand All @@ -176,7 +180,7 @@ def positioning_scope_was
end

def in_positioning_scope?
@positioned.persisted? && positioning_scope.where("#{primary_key_column}": primary_key).exists?
@positioned.persisted? && positioning_scope.where(Array(primary_key_column).zip(Array(primary_key)).to_h).exists?
end

def positioning_scope_changed?
Expand Down
5 changes: 5 additions & 0 deletions test/models/item_with_composite_primary_key.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class ItemWithCompositePrimaryKey < ActiveRecord::Base
belongs_to :list

positioned on: :list
end
1 change: 1 addition & 0 deletions test/models/list.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class List < ActiveRecord::Base
has_many :items, -> { order(:position) }, dependent: :destroy
has_many :item_without_advisory_locks, -> { order(:position) }, dependent: :destroy
has_many :item_with_composite_primary_keys, -> { order(:position) }, dependent: :destroy
has_many :authors, -> { order(:position) }, dependent: :destroy
end
10 changes: 10 additions & 0 deletions test/support/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@

add_index :item_without_advisory_locks, [:list_id, :position], unique: true

create_table :item_with_composite_primary_keys, primary_key: [:item_id, :account_id], force: true do |t|
t.integer :item_id, null: false
t.integer :account_id, null: false
t.string :name
t.integer :position, null: false
t.references :list, null: false
end

add_index :item_with_composite_primary_keys, [:list_id, :position], unique: true

create_table :categories, force: true do |t|
t.string :name
t.integer :position, null: false
Expand Down
9 changes: 9 additions & 0 deletions test/test_positioning.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require_relative "models/list"
require_relative "models/item"
require_relative "models/item_without_advisory_lock"
require_relative "models/item_with_composite_primary_key"
require_relative "models/category"
require_relative "models/categorised_item"
require_relative "models/author"
Expand Down Expand Up @@ -175,6 +176,14 @@ def test_primary_key
assert_equal student.id, mechanisms.send(:primary_key)
end

def test_composite_primary_key
list = List.create name: "List"
item = list.item_with_composite_primary_keys.create item_id: "1", account_id: "1"

mechanisms = Positioning::Mechanisms.new(item, :position)
assert_equal item.id, mechanisms.send(:primary_key)
end

def test_record_scope
list = List.create name: "List"
student = list.authors.create name: "Student", type: "Author::Student"
Expand Down

0 comments on commit f855c01

Please sign in to comment.