add filtered_column type
This commit is contained in:
parent
4e0d3c2df1
commit
d54ab64e40
6 changed files with 130 additions and 10 deletions
12
app/models/filtered_column.rb
Normal file
12
app/models/filtered_column.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FilteredColumn
|
||||||
|
def initialize(column:, filter:)
|
||||||
|
@column = column
|
||||||
|
@filter = filter
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
other&.column == column && other.filter == filter
|
||||||
|
end
|
||||||
|
end
|
|
@ -25,14 +25,14 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
attribute :sorted_column, :sorted_column
|
attribute :sorted_column, :sorted_column
|
||||||
def sorted_column = super || procedure.default_sorted_column # Dummy override to set default value
|
def sorted_column = super || procedure.default_sorted_column # Dummy override to set default value
|
||||||
|
|
||||||
attribute :a_suivre_filters, :jsonb, array: true
|
attribute :a_suivre_filters, :filtered_column, array: true
|
||||||
attribute :suivis_filters, :jsonb, array: true
|
attribute :suivis_filters, :filtered_column, array: true
|
||||||
attribute :traites_filters, :jsonb, array: true
|
attribute :traites_filters, :filtered_column, array: true
|
||||||
attribute :tous_filters, :jsonb, array: true
|
attribute :tous_filters, :filtered_column, array: true
|
||||||
attribute :supprimes_filters, :jsonb, array: true
|
attribute :supprimes_filters, :filtered_column, array: true
|
||||||
attribute :supprimes_recemment_filters, :jsonb, array: true
|
attribute :supprimes_recemment_filters, :filtered_column, array: true
|
||||||
attribute :expirant_filters, :jsonb, array: true
|
attribute :expirant_filters, :filtered_column, array: true
|
||||||
attribute :archives_filters, :jsonb, array: true
|
attribute :archives_filters, :filtered_column, array: true
|
||||||
|
|
||||||
def filters_for(statut)
|
def filters_for(statut)
|
||||||
send(filters_name_for(statut))
|
send(filters_name_for(statut))
|
||||||
|
|
36
app/types/filtered_column_type.rb
Normal file
36
app/types/filtered_column_type.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FilteredColumnType < 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 FilteredColumn
|
||||||
|
value
|
||||||
|
in NilClass # default value
|
||||||
|
nil
|
||||||
|
# from form (id is a string) or from db (id is a hash)
|
||||||
|
in { id: String|Hash, filter: String } => h
|
||||||
|
FilteredColumn.new(column: ColumnType.new.cast(h[:id]), filter: h[:filter])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# db -> ruby
|
||||||
|
def deserialize(value) = cast(value&.then { JSON.parse(_1) })
|
||||||
|
|
||||||
|
# ruby -> db
|
||||||
|
def serialize(value)
|
||||||
|
case value
|
||||||
|
in NilClass
|
||||||
|
nil
|
||||||
|
in FilteredColumn
|
||||||
|
JSON.generate({
|
||||||
|
id: value.column.h_id,
|
||||||
|
filter: value.filter
|
||||||
|
})
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Invalid value for FilteredColumn serialization: #{value}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,9 +3,11 @@
|
||||||
require Rails.root.join("app/types/column_type")
|
require Rails.root.join("app/types/column_type")
|
||||||
require Rails.root.join("app/types/export_item_type")
|
require Rails.root.join("app/types/export_item_type")
|
||||||
require Rails.root.join("app/types/sorted_column_type")
|
require Rails.root.join("app/types/sorted_column_type")
|
||||||
|
require Rails.root.join("app/types/filtered_column_type")
|
||||||
|
|
||||||
ActiveSupport.on_load(:active_record) do
|
ActiveSupport.on_load(:active_record) do
|
||||||
ActiveRecord::Type.register(:column, ColumnType)
|
ActiveRecord::Type.register(:column, ColumnType)
|
||||||
ActiveRecord::Type.register(:export_item, ExportItemType)
|
ActiveRecord::Type.register(:export_item, ExportItemType)
|
||||||
ActiveRecord::Type.register(:sorted_column, SortedColumnType)
|
ActiveRecord::Type.register(:sorted_column, SortedColumnType)
|
||||||
|
ActiveRecord::Type.register(:filtered_column, FilteredColumnType)
|
||||||
end
|
end
|
||||||
|
|
|
@ -94,7 +94,9 @@ RSpec.describe Export, type: :model do
|
||||||
let(:instructeur) { create(:instructeur) }
|
let(:instructeur) { create(:instructeur) }
|
||||||
let!(:gi_1) { create(:groupe_instructeur, procedure: procedure, instructeurs: [instructeur]) }
|
let!(:gi_1) { create(:groupe_instructeur, procedure: procedure, instructeurs: [instructeur]) }
|
||||||
let!(:pp) { gi_1.instructeurs.first.procedure_presentation_and_errors_for_procedure_id(procedure.id).first }
|
let!(:pp) { gi_1.instructeurs.first.procedure_presentation_and_errors_for_procedure_id(procedure.id).first }
|
||||||
before { pp.add_filter('tous', procedure.find_column(label: 'Créé le').id, '10/12/2021') }
|
let(:created_at_column) { FilteredColumn.new(column: procedure.find_column(label: 'Créé le'), filter: '10/12/2021') }
|
||||||
|
|
||||||
|
before { pp.update(tous_filters: [created_at_column]) }
|
||||||
|
|
||||||
context 'with procedure_presentation having different filters' do
|
context 'with procedure_presentation having different filters' do
|
||||||
it 'works once' do
|
it 'works once' do
|
||||||
|
@ -105,7 +107,10 @@ RSpec.describe Export, type: :model do
|
||||||
it 'works once, changes procedure_presentation, recreate a new' do
|
it 'works once, changes procedure_presentation, recreate a new' do
|
||||||
expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||||
.to change { Export.count }.by(1)
|
.to change { Export.count }.by(1)
|
||||||
pp.add_filter('tous', procedure.find_column(label: 'Mis à jour le').id, '10/12/2021')
|
|
||||||
|
update_at_column = FilteredColumn.new(column: procedure.find_column(label: 'Mis à jour le'), filter: '10/12/2021')
|
||||||
|
pp.update(tous_filters: [created_at_column, update_at_column])
|
||||||
|
|
||||||
expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) }
|
||||||
.to change { Export.count }.by(1)
|
.to change { Export.count }.by(1)
|
||||||
end
|
end
|
||||||
|
|
65
spec/types/filtered_column_type_spec.rb
Normal file
65
spec/types/filtered_column_type_spec.rb
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe FilteredColumnType do
|
||||||
|
let(:type) { FilteredColumnType.new }
|
||||||
|
|
||||||
|
describe 'cast' do
|
||||||
|
it 'from FilteredColumn' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
filtered_column = FilteredColumn.new(column:, filter: 'filter')
|
||||||
|
expect(type.cast(filtered_column)).to eq(filtered_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 = { filter: 'filter', id: column.id }
|
||||||
|
|
||||||
|
expect(Column).to receive(:find).with(column.h_id).and_return(column)
|
||||||
|
expect(type.cast(h)).to eq(FilteredColumn.new(column:, filter: 'filter'))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with invalid column id' do
|
||||||
|
h = { filter: 'filter', id: 'invalid' }
|
||||||
|
expect { type.cast(h) }.to raise_error(JSON::ParserError)
|
||||||
|
|
||||||
|
h = { filter: 'filter', id: { procedure_id: 'invalid', column_id: 'nop' }.to_json }
|
||||||
|
expect { type.cast(h) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
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, filter: 'filter' }.to_json)).to eq(FilteredColumn.new(column: column, filter: 'filter'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with nil' do
|
||||||
|
it { expect(type.deserialize(nil)).to eq(nil) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'serialize' do
|
||||||
|
it 'with FilteredColumn' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
sorted_column = FilteredColumn.new(column: column, filter: 'filter')
|
||||||
|
expect(type.serialize(sorted_column)).to eq({ id: column.h_id, filter: 'filter' }.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
|
Loading…
Reference in a new issue