refactor(conditional): extract in a ChampConditionalConcern with tests

This commit is contained in:
Colin Darie 2023-01-04 13:09:14 +01:00
parent 7c13449b4f
commit 51c1736d00
4 changed files with 72 additions and 23 deletions

View file

@ -21,6 +21,8 @@
# type_de_champ_id :integer # type_de_champ_id :integer
# #
class Champ < ApplicationRecord class Champ < ApplicationRecord
include ChampConditionalConcern
belongs_to :dossier, inverse_of: false, touch: true, optional: false belongs_to :dossier, inverse_of: false, touch: true, optional: false
belongs_to :type_de_champ, inverse_of: :champ, optional: false belongs_to :type_de_champ, inverse_of: :champ, optional: false
belongs_to :parent, class_name: 'Champ', optional: true belongs_to :parent, class_name: 'Champ', optional: true
@ -209,25 +211,6 @@ class Champ < ApplicationRecord
raise NotImplemented.new(:fetch_external_data) raise NotImplemented.new(:fetch_external_data)
end end
def conditional?
type_de_champ.read_attribute_before_type_cast('condition').present?
end
def dependent_conditions?
dossier.revision.dependent_conditions(type_de_champ).any?
end
def visible?
# Huge gain perf for cascade conditions
return @visible if instance_variable_defined? :@visible
@visible = if conditional?
type_de_champ.condition.compute(champs_for_condition)
else
true
end
end
def clone def clone
champ_attributes = [:parent_id, :private, :row_id, :type, :type_de_champ_id] champ_attributes = [:parent_id, :private, :row_id, :type, :type_de_champ_id]
value_attributes = private? ? [] : [:value, :value_json, :data, :external_id] value_attributes = private? ? [] : [:value, :value_json, :data, :external_id]
@ -240,10 +223,6 @@ class Champ < ApplicationRecord
private private
def champs_for_condition
dossier.champs.filter { _1.row_id.nil? || _1.row_id == row_id }
end
def html_id def html_id
"#{stable_id}-#{id}" "#{stable_id}-#{id}"
end end

View file

@ -0,0 +1,30 @@
module ChampConditionalConcern
extend ActiveSupport::Concern
included do
def conditional?
type_de_champ.read_attribute_before_type_cast('condition').present?
end
def dependent_conditions?
dossier.revision.dependent_conditions(type_de_champ).any?
end
def visible?
# Huge gain perf for cascade conditions
return @visible if instance_variable_defined? :@visible
@visible = if conditional?
type_de_champ.condition.compute(champs_for_condition)
else
true
end
end
private
def champs_for_condition
dossier.champs.filter { _1.row_id.nil? || _1.row_id == row_id }
end
end
end

View file

@ -0,0 +1,23 @@
describe ChampConditionalConcern do
include Logic
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :number }, { type: :number }]) }
let(:dossier) { create(:dossier, revision: procedure.active_revision) }
let(:types_de_champ) { procedure.active_revision.types_de_champ_public }
let(:champ) { create(:champ, dossier:, type_de_champ: types_de_champ.first, value: 1) }
describe '#dependent_conditions?' do
context "when there are no condition" do
it { expect(champ.dependent_conditions?).to eq(false) }
end
context "when other tdc has a condition" do
before do
condition = ds_eq(champ_value(champ.stable_id), constant(1))
types_de_champ.last.update!(condition:)
end
it { expect(champ.dependent_conditions?).to eq(true) }
end
end
end

View file

@ -855,4 +855,21 @@ describe ProcedureRevision do
it { expect(subject.first.attribute).to eq(:condition) } it { expect(subject.first.attribute).to eq(:condition) }
end end
end end
describe "#dependent_conditions" do
include Logic
def first_champ = procedure.draft_revision.types_de_champ_public.first
def second_champ = procedure.draft_revision.types_de_champ_public.second
let(:procedure) do
create(:procedure).tap do |p|
tdc = p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'l1')
p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'l2', condition: ds_eq(champ_value(tdc.stable_id), constant(true)))
end
end
it { expect(draft.dependent_conditions(first_champ)).to eq([second_champ]) }
it { expect(draft.dependent_conditions(second_champ)).to eq([]) }
end
end end