diff --git a/app/controllers/default/units_controller.rb b/app/controllers/default/units_controller.rb index e2255e9..ea47bbb 100644 --- a/app/controllers/default/units_controller.rb +++ b/app/controllers/default/units_controller.rb @@ -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 diff --git a/app/controllers/units_controller.rb b/app/controllers/units_controller.rb index 2231f04..f48cfef 100644 --- a/app/controllers/units_controller.rb +++ b/app/controllers/units_controller.rb @@ -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 diff --git a/app/models/unit.rb b/app/models/unit.rb index 5abe06d..2a5fa26 100644 --- a/app/models/unit.rb +++ b/app/models/unit.rb @@ -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 diff --git a/app/models/user.rb b/app/models/user.rb index 900d6ea..3c43d9b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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] diff --git a/app/views/default/units/_unit.html.erb b/app/views/default/units/_unit.html.erb index 7785b6b..53d8889 100644 --- a/app/views/default/units/_unit.html.erb +++ b/app/views/default/units/_unit.html.erb @@ -5,7 +5,8 @@