First part of portability checks

This commit is contained in:
cryptogopher 2024-11-15 02:02:19 +01:00
parent a01c89ce3a
commit 4447735dce
5 changed files with 29 additions and 11 deletions

View File

@ -13,7 +13,7 @@ class Default::UnitsController < ApplicationController
end
def index
@units = current_user.units.defaults_diff
@units = current_user.units.defaults_diff.includes(:base).ordered
end
def import

View File

@ -9,7 +9,7 @@ class UnitsController < ApplicationController
end
def index
@units = current_user.units.includes(:subunits)
@units = current_user.units.includes(:subunits).ordered
end
def new

View File

@ -16,21 +16,34 @@ class Unit < ApplicationRecord
scope :defaults, ->{ where(user: nil) }
scope :with_defaults, ->{ self.or(Unit.where(user: nil)) }
scope :defaults_diff, ->{
other_units = Unit.arel_table.alias('other_units')
other_bases_units = Unit.arel_table.alias('other_bases_units')
bases_units = arel_table.alias('bases_units')
other_units = arel_table.alias('other_units')
other_bases_units = arel_table.alias('other_bases_units')
parent_units = arel_table.alias('parent_units')
# add 'portable' fields (import on !default == export) to select
with_defaults
with(units: self.with_defaults).unscope(where: :user_id).left_joins(:base)
.where.not(
Arel::SelectManager.new.from(other_units)
Arel::SelectManager.new.project(1).from(other_units)
.outer_join(other_bases_units)
.on(other_units[:base_id].eq(other_bases_units[:id]))
.where(
other_bases_units[:symbol].eq(Arel::Table.new(:bases_units)[:symbol])
other_bases_units[:symbol].eq(bases_units[:symbol])
.and(other_units[:symbol].eq(arel_table[:symbol]))
.and(other_units[:user_id].not_eq(arel_table[:user_id]))
).project(1).exists
).exists
).joins(
arel_table.create_join(parent_units,
arel_table.create_on(
parent_units[:symbol].eq(bases_units[:symbol])
.and(parent_units[:user_id].not_eq(bases_units[:user_id]))
),
Arel::Nodes::OuterJoin)
).select(
arel_table[Arel.star],
Arel::Nodes::IsNotDistinctFrom.new(parent_units[:symbol], bases_units[:symbol])
.as('portable')
)
# complete portability check with children
}
scope :ordered, ->{
left_outer_joins(:base)
@ -50,4 +63,8 @@ class Unit < ApplicationRecord
def default?
user.nil?
end
def exportable?
!default? && (base.nil? || base.default?)
end
end

View File

@ -11,7 +11,7 @@ class User < ApplicationRecord
disabled: 0, # administratively disallowed to sign in
}, default: :active
has_many :units, -> { ordered }, dependent: :destroy
has_many :units, dependent: :destroy
def at_least(status)
User.statuses[self.status] >= User.statuses[status]

View File

@ -5,7 +5,8 @@
<td class="actions">
<% if current_user.at_least(:active) && unit.default? %>
<%= image_button_to t('.import'), 'download-outline', import_default_unit_path(unit) %>
<%= image_button_to t('.import'), 'download-outline', import_default_unit_path(unit),
disabled: !unit.portable? %>
<% end %>
<% if current_user.at_least(:admin) %>
<% if !unit.default? %>