From 42488419b583bd0ff919812b07462eeb17b71a8c Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 9 Jun 2022 15:25:49 +0200 Subject: [PATCH] add condition form model --- app/models/condition_form.rb | 58 ++++++++++++++++++++++++++++++ spec/models/condition_form_spec.rb | 52 +++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 app/models/condition_form.rb create mode 100644 spec/models/condition_form_spec.rb diff --git a/app/models/condition_form.rb b/app/models/condition_form.rb new file mode 100644 index 000000000..abd80109c --- /dev/null +++ b/app/models/condition_form.rb @@ -0,0 +1,58 @@ +class ConditionForm + include ActiveModel::Model + include Logic + + attr_accessor :top_operator_name, :rows + + def to_condition + case sub_conditions.count + when 0 + nil + when 1 + sub_conditions.first + else + top_operator_class.new(sub_conditions) + end + end + + def delete_row(i) + rows.slice!(i) + + self + end + + def change_champ(i) + sub_conditions[i] = Logic.ensure_compatibility_from_left(sub_conditions[i]) + + self + end + + private + + def top_operator_class + Logic.class_from_name(top_operator_name) + end + + def sub_conditions + @sub_conditions ||= rows.map { |row| row_to_condition(row) } + end + + def row_to_condition(row) + left = Logic.from_json(row[:targeted_champ]) + right = parse_value(row[:value]) + + Logic.class_from_name(row[:operator_name]).new(left, right) + end + + def parse_value(value) + return empty if value.blank? + + number = Integer(value) rescue nil + return constant(number) if number.present? + + json = JSON.parse(value) rescue nil + return Logic.from_json(value) if json.present? + + constant(value) + end +end diff --git a/spec/models/condition_form_spec.rb b/spec/models/condition_form_spec.rb new file mode 100644 index 000000000..182001f84 --- /dev/null +++ b/spec/models/condition_form_spec.rb @@ -0,0 +1,52 @@ +describe ConditionForm, type: :model do + include Logic + + describe 'to_condition' do + let(:top_operator_name) { '' } + + subject { ConditionForm.new(rows: rows, top_operator_name: top_operator_name).to_condition } + + context 'when a row is added' do + let(:rows) { [{ targeted_champ: champ_value(1).to_json, operator_name: Logic::Eq.name, value: '1' }] } + it { is_expected.to eq(ds_eq(champ_value(1), constant(1))) } + end + + context 'when two rows are added' do + let(:top_operator_name) { Logic::And.name } + let(:rows) do + [ + { targeted_champ: champ_value(1).to_json, operator_name: Logic::Eq.name, value: '2' }, + { targeted_champ: champ_value(3).to_json, operator_name: Logic::GreaterThan.name, value: '4' } + ] + end + + let(:expected) do + ds_and([ + ds_eq(champ_value(1), constant(2)), + greater_than(champ_value(3), constant(4)) + ]) + end + it { is_expected.to eq(expected) } + end + + context 'when 3 rows are added' do + let(:top_operator_name) { Logic::Or.name } + let(:rows) do + [ + { targeted_champ: champ_value(1).to_json, operator_name: Logic::Eq.name, value: '2' }, + { targeted_champ: champ_value(3).to_json, operator_name: Logic::GreaterThan.name, value: '4' }, + { targeted_champ: champ_value(5).to_json, operator_name: Logic::LessThan.name, value: '6' } + ] + end + + let(:expected) do + ds_or([ + ds_eq(champ_value(1), constant(2)), + greater_than(champ_value(3), constant(4)), + less_than(champ_value(5), constant(6)) + ]) + end + it { is_expected.to eq(expected) } + end + end +end