From 21533f91e36162717663a46bbdb784ffa70a7a84 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 25 Sep 2024 17:41:58 +0200 Subject: [PATCH] add storted_column_type --- app/models/procedure_presentation.rb | 3 +- app/types/sorted_column_type.rb | 36 ++++++++++ config/initializers/types.rb | 2 + ...edure_presentation_to_columns.rake_spec.rb | 4 +- spec/types/sorted_column_type_spec.rb | 71 +++++++++++++++++++ 5 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 app/types/sorted_column_type.rb create mode 100644 spec/types/sorted_column_type_spec.rb diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 6607f8adc..d3e08befd 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -29,7 +29,8 @@ class ProcedurePresentation < ApplicationRecord validate :check_filters_max_length validate :check_filters_max_integer - attribute :sorted_column, :jsonb + attribute :sorted_column, :sorted_column + def sorted_column = super || procedure.default_sorted_column # Dummy override to set default value attribute :a_suivre_filters, :jsonb, array: true attribute :suivis_filters, :jsonb, array: true diff --git a/app/types/sorted_column_type.rb b/app/types/sorted_column_type.rb new file mode 100644 index 000000000..b9daae095 --- /dev/null +++ b/app/types/sorted_column_type.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class SortedColumnType < ActiveRecord::Type::Value + # form_input or setter -> type + def cast(value) + value = value.deep_symbolize_keys if value.respond_to?(:deep_symbolize_keys) + + case value + in SortedColumn + value + in NilClass # default value + nil + # from form (id is a string) or from db (id is a hash) + in { order: 'asc'|'desc', id: String|Hash } => h + SortedColumn.new(column: ColumnType.new.cast(h[:id]), order: h[:order]) + end + end + + # db -> ruby + def deserialize(value) = cast(value&.then { JSON.parse(_1) }) + + # ruby -> db + def serialize(value) + case value + in NilClass + nil + in SortedColumn + JSON.generate({ + id: value.column.h_id, + order: value.order + }) + else + raise ArgumentError, "Invalid value for SortedColumn serialization: #{value}" + end + end +end diff --git a/config/initializers/types.rb b/config/initializers/types.rb index a77b4b64d..8ac4a38ed 100644 --- a/config/initializers/types.rb +++ b/config/initializers/types.rb @@ -2,8 +2,10 @@ require Rails.root.join("app/types/column_type") require Rails.root.join("app/types/export_item_type") +require Rails.root.join("app/types/sorted_column_type") ActiveSupport.on_load(:active_record) do ActiveRecord::Type.register(:column, ColumnType) ActiveRecord::Type.register(:export_item, ExportItemType) + ActiveRecord::Type.register(:sorted_column, SortedColumnType) end diff --git a/spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb b/spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb index 6545cf027..46c868f03 100644 --- a/spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb +++ b/spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb @@ -45,10 +45,10 @@ describe '20240920130741_migrate_procedure_presentation_to_columns.rake' do order, column_id = procedure_presentation .sorted_column - .then { |sorted| [sorted['order'], sorted['id']] } + .then { |sorted| [sorted.order, sorted.column.h_id] } expect(order).to eq('desc') - expect(column_id).to eq("procedure_id" => procedure_id, "column_id" => "self/en_construction_at") + expect(column_id).to eq(procedure_id: procedure_id, column_id: "self/en_construction_at") expect(procedure_presentation.tous_filters).to eq([]) diff --git a/spec/types/sorted_column_type_spec.rb b/spec/types/sorted_column_type_spec.rb new file mode 100644 index 000000000..067c41fb5 --- /dev/null +++ b/spec/types/sorted_column_type_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +describe SortedColumnType do + let(:type) { SortedColumnType.new } + + describe 'cast' do + it 'from SortedColumn' do + column = Column.new(procedure_id: 1, table: 'table', column: 'column') + sorted_column = SortedColumn.new(column:, order: 'asc') + expect(type.cast(sorted_column)).to eq(sorted_column) + end + + it 'from nil' do + expect(type.cast(nil)).to eq(nil) + end + + describe 'from form' do + it 'with valid column id' do + column = Column.new(procedure_id: 1, table: 'table', column: 'column') + h = { order: 'asc', id: column.id } + + expect(Column).to receive(:find).with(column.h_id).and_return(column) + expect(type.cast(h)).to eq(SortedColumn.new(column: column, order: 'asc')) + end + + it 'with invalid column id' do + h = { order: 'asc', id: 'invalid' } + expect { type.cast(h) }.to raise_error(JSON::ParserError) + + h = { order: 'asc', id: { procedure_id: 'invalid', column_id: 'nop' }.to_json } + expect { type.cast(h) }.to raise_error(ActiveRecord::RecordNotFound) + end + + it 'with invalid order' do + column = Column.new(procedure_id: 1, table: 'table', column: 'column') + h = { order: 'invalid', id: column.id } + expect { type.cast(h) }.to raise_error(NoMatchingPatternError) + end + end + end + + describe 'deserialize' do + context 'with valid value' do + it 'works' do + column = Column.new(procedure_id: 1, table: 'table', column: 'column') + expect(Column).to receive(:find).with(column.h_id).and_return(column) + expect(type.deserialize({ id: column.h_id, order: 'asc' }.to_json)).to eq(SortedColumn.new(column: column, order: 'asc')) + end + end + + context 'with nil' do + it { expect(type.deserialize(nil)).to eq(nil) } + end + end + + describe 'serialize' do + it 'with SortedColumn' do + column = Column.new(procedure_id: 1, table: 'table', column: 'column') + sorted_column = SortedColumn.new(column: column, order: 'asc') + expect(type.serialize(sorted_column)).to eq({ id: column.h_id, order: 'asc' }.to_json) + end + + it 'with nil' do + expect(type.serialize(nil)).to eq(nil) + end + + it 'with invalid value' do + expect { type.serialize('invalid') }.to raise_error(ArgumentError) + end + end +end