Merge pull request #7521 from betagouv/work_on_logic

feat: amélioration sur le module de logic
This commit is contained in:
LeSim 2022-07-05 12:11:33 +02:00 committed by GitHub
commit 222cb1e557
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 96 additions and 43 deletions

View file

@ -27,8 +27,6 @@ module Logic
in [:number, EmptyOperator]
operator_class = Eq
in [:number, _]
in [:string, _]
operator_class = Eq
end
if !compatible_type?(left, right)
@ -41,8 +39,6 @@ module Logic
Constant.new(left.options.first)
when :number
Constant.new(0)
when :string
Constant.new('')
end
end
@ -60,6 +56,18 @@ module Logic
end
end
def self.add_empty_condition_to(condition)
empty_condition = EmptyOperator.new(Empty.new, Empty.new)
if condition.nil?
empty_condition
elsif [And, Or].include?(condition.class)
condition.tap { |c| c.operands << empty_condition }
else
Logic::And.new([condition, empty_condition])
end
end
def ds_eq(left, right) = Logic::Eq.new(left, right)
def greater_than(left, right) = Logic::GreaterThan.new(left, right)

View file

@ -1,4 +1,20 @@
class Logic::ChampValue < Logic::Term
MANAGED_TYPE_DE_CHAMP = TypeDeChamp.type_champs.slice(
:yes_no,
:checkbox,
:integer_number,
:decimal_number,
:drop_down_list
)
CHAMP_VALUE_TYPE = {
boolean: :boolean,
number: :number,
enum: :enum,
empty: :empty,
unmanaged: :unmanaged
}
attr_reader :stable_id
def initialize(stable_id)
@ -7,12 +23,12 @@ class Logic::ChampValue < Logic::Term
def compute(champs)
case type_de_champ.type_champ
when all_types.fetch(:yes_no),
all_types.fetch(:checkbox)
when MANAGED_TYPE_DE_CHAMP.fetch(:yes_no),
MANAGED_TYPE_DE_CHAMP.fetch(:checkbox)
champ(champs).true?
when all_types.fetch(:integer_number), all_types.fetch(:decimal_number)
when MANAGED_TYPE_DE_CHAMP.fetch(:integer_number), MANAGED_TYPE_DE_CHAMP.fetch(:decimal_number)
champ(champs).for_api
when all_types.fetch(:drop_down_list), all_types.fetch(:text)
when MANAGED_TYPE_DE_CHAMP.fetch(:drop_down_list)
champ(champs).value
end
end
@ -21,15 +37,15 @@ class Logic::ChampValue < Logic::Term
def type
case type_de_champ.type_champ
when all_types.fetch(:yes_no),
all_types.fetch(:checkbox)
:boolean
when all_types.fetch(:integer_number), all_types.fetch(:decimal_number)
:number
when all_types.fetch(:text)
:string
when all_types.fetch(:drop_down_list)
:enum
when MANAGED_TYPE_DE_CHAMP.fetch(:yes_no),
MANAGED_TYPE_DE_CHAMP.fetch(:checkbox)
CHAMP_VALUE_TYPE.fetch(:boolean)
when MANAGED_TYPE_DE_CHAMP.fetch(:integer_number), MANAGED_TYPE_DE_CHAMP.fetch(:decimal_number)
CHAMP_VALUE_TYPE.fetch(:number)
when MANAGED_TYPE_DE_CHAMP.fetch(:drop_down_list)
CHAMP_VALUE_TYPE.fetch(:enum)
else
CHAMP_VALUE_TYPE.fetch(:unmanaged)
end
end
@ -69,8 +85,4 @@ class Logic::ChampValue < Logic::Term
def champ(champs)
champs.find { |c| c.stable_id == stable_id }
end
def all_types
TypeDeChamp.type_champs
end
end

View file

@ -7,7 +7,16 @@ class Logic::Constant < Logic::Term
def compute(_champs = nil) = @value
def to_s = @value.to_s
def to_s
case @value
when TrueClass
I18n.t('utils.yes')
when FalseClass
I18n.t('utils.no')
else
@value.to_s
end
end
def type
case @value

View file

@ -1,5 +1,5 @@
class Logic::Empty < Logic::Term
def to_s = "empty member"
def to_s = I18n.t('logic.empty')
def type = :empty
@ -18,4 +18,8 @@ class Logic::Empty < Logic::Term
def ==(other)
self.class == other.class
end
def value
nil
end
end

View file

@ -3,5 +3,9 @@ class Logic::EmptyOperator < Logic::BinaryOperator
def type = :empty
def errors(_stable_ids = nil) = ['empty']
def errors(_stable_ids = nil) = []
def compute(_champs = [])
true
end
end

View file

@ -0,0 +1,3 @@
en:
logic:
empty: empty member

View file

@ -0,0 +1,3 @@
fr:
logic:
empty: un membre vide

View file

@ -8,7 +8,7 @@ describe Logic::And do
describe '#to_s' do
it do
expect(and_from([true, false, true]).to_s).to eq "(true && false && true)"
expect(and_from([true, false, true]).to_s).to eq "(Oui && Non && Oui)"
end
end

View file

@ -16,7 +16,7 @@ describe Logic::BinaryOperator do
end
describe '#errors' do
it { expect(greater_than(constant(1), constant(true)).errors).to eq(['les types sont incompatibles : (1 > true)']) }
it { expect(greater_than(constant(1), constant(true)).errors).to eq(['les types sont incompatibles : (1 > Oui)']) }
end
end

View file

@ -20,13 +20,6 @@ describe Logic::ChampValue do
end
end
context 'text tdc' do
let(:champ) { create(:champ_text, value: 'text') }
it { expect(champ_value(champ.stable_id).type).to eq(:string) }
it { is_expected.to eq('text') }
end
context 'integer tdc' do
let(:champ) { create(:champ_integer_number, value: '42') }

View file

@ -0,0 +1,7 @@
describe Logic::EmptyOperator do
include Logic
describe '#compute' do
it { expect(empty_operator(empty, empty).compute).to be true }
end
end

View file

@ -13,4 +13,8 @@ describe Logic::Constant do
it { expect(empty).to eq(empty) }
it { expect(empty).not_to eq(constant(true)) }
end
describe '#to_s' do
it { expect(empty.to_s).to eq('un membre vide') }
end
end

View file

@ -8,7 +8,7 @@ describe Logic::Eq do
describe '#errors' do
it { expect(ds_eq(constant(true), constant(true)).errors).to be_empty }
it { expect(ds_eq(constant(true), constant(1)).errors).to eq(["les types sont incompatibles : (true == 1)"]) }
it { expect(ds_eq(constant(true), constant(1)).errors).to eq(["les types sont incompatibles : (Oui == 1)"]) }
end
describe '#==' do

View file

@ -8,7 +8,7 @@ describe Logic::Or do
end
describe '#to_s' do
it { expect(or_from([true, false, true]).to_s).to eq "(true || false || true)" }
it { expect(or_from([true, false, true]).to_s).to eq "(Oui || Non || Oui)" }
end
def or_from(boolean_to_constants)

View file

@ -42,12 +42,6 @@ describe Logic do
it { is_expected.to eq(ds_eq(constant(1), constant(0))) }
end
context 'when string empty operator true' do
let(:condition) { empty_operator(constant('a'), constant(true)) }
it { is_expected.to eq(ds_eq(constant('a'), constant(''))) }
end
context 'when dropdown empty operator true' do
let(:drop_down) { create(:type_de_champ_drop_down_list) }
let(:first_option) { drop_down.drop_down_list_enabled_non_empty_options.first }
@ -79,4 +73,10 @@ describe Logic do
# false && (true || true) = false
it { expect(ds_and([constant(false), ds_or([constant(true), constant(true)])]).compute).to be false }
end
describe '.add_empty_condition_to' do
it { expect(Logic.add_empty_condition_to(nil)).to eq(empty_operator(empty, empty)) }
it { expect(Logic.add_empty_condition_to(constant(true))).to eq(ds_and([constant(true), empty_operator(empty, empty)])) }
it { expect(Logic.add_empty_condition_to(ds_or([constant(true)]))).to eq(ds_or([constant(true), empty_operator(empty, empty)])) }
end
end

View file

@ -631,7 +631,13 @@ describe ProcedureRevision do
def second_champ = procedure.draft_revision.types_de_champ_public.second
let(:procedure) { create(:procedure, :with_type_de_champ, types_de_champ_count: 2) }
let(:procedure) do
create(:procedure).tap do |p|
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')
end
end
let(:draft_revision) { procedure.draft_revision }
let(:condition) { nil }
@ -649,7 +655,7 @@ describe ProcedureRevision do
end
context 'when a champ has a valid condition: needed tdc is up in the forms' do
let(:condition) { ds_eq(constant('oui'), champ_value(first_champ.stable_id)) }
let(:condition) { ds_eq(champ_value(first_champ.stable_id), constant(1)) }
it { is_expected.to be_empty }
end