diff --git a/.rubocop.yml b/.rubocop.yml index 02ed7a244..170a0078e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -233,6 +233,7 @@ Metrics/ClassLength: - 'packages/forest_admin_agent/lib/forest_admin_agent/services/permissions.rb' - 'packages/forest_admin_agent/lib/forest_admin_agent/routes/charts/charts.rb' - 'packages/forest_admin_agent/lib/forest_admin_agent/routes/action/action.rb' + - 'packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query.rb' - 'packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/collection_customizer.rb' - 'packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/binary/binary_collection_decorator.rb' - 'packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb' diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb b/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb index 2abfb06ff..53c0de97b 100644 --- a/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb +++ b/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb @@ -106,15 +106,24 @@ def self.parse_search_extended(args) end def self.parse_sort(collection, args) - sort_string = args.dig(:params, :sort) + raw_sort_string = args.dig(:params, :sort) - return SortUtils::SortFactory.by_primary_keys(collection) unless sort_string + return SortUtils::SortFactory.by_primary_keys(collection) unless raw_sort_string - sort = Sort.new([ - { field: sort_string.gsub(/^-/, '').tr('.', ':'), ascending: !sort_string.start_with?('-') } - ]) + sort_list = [] + raw_sort_string.split(',').map do |sort_string| + field = sort_string.tr('.', ':') + ascending = !sort_string.start_with?('-') + field = field[1..] unless ascending + + sort_list.push({ field: field, ascending: ascending }) + end + + sort = Sort.new(sort_list) ForestAdminDatasourceToolkit::Validations::SortValidator.validate(collection, sort) + + sort end end end diff --git a/packages/forest_admin_agent/spec/lib/forest_admin_agent/utils/query_string_parser_spec.rb b/packages/forest_admin_agent/spec/lib/forest_admin_agent/utils/query_string_parser_spec.rb index 2f30a4c3c..2844de3b7 100644 --- a/packages/forest_admin_agent/spec/lib/forest_admin_agent/utils/query_string_parser_spec.rb +++ b/packages/forest_admin_agent/spec/lib/forest_admin_agent/utils/query_string_parser_spec.rb @@ -489,6 +489,33 @@ module Utils "🌳🌳🌳 Column not found: 'User.fieldThatDoNotExist'" ) end + + describe 'when sending multiple sort' do + it 'returns the sort clauses' do + args = { + params: { + sort: 'name,-id' + } + } + + expect(described_class.parse_sort(collection_user, args)).to eq([{ field: 'name', ascending: true }, { field: 'id', ascending: false }]) + end + + it 'throws a ValidationError when one of the sorting field is invalid' do + args = { + params: { + sort: 'name,-fieldThatDoesNotExist' + } + } + + expect do + described_class.parse_sort(collection_user, args) + end.to raise_error( + ForestAdminDatasourceToolkit::Exceptions::ForestException, + '🌳🌳🌳 Column not found: \'User.fieldThatDoesNotExist\'' + ) + end + end end end end diff --git a/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query.rb b/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query.rb index 7862916a5..052c0cad5 100644 --- a/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query.rb +++ b/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query.rb @@ -21,6 +21,16 @@ def build def apply_filter @query = apply_condition_tree(@filter.condition_tree) unless @filter.condition_tree.nil? @query = apply_pagination(@filter.page) unless @filter.page.nil? + @query = apply_sort(@filter.sort) unless @filter.sort.nil? + + @query + end + + def apply_sort(sort) + sort.each do |sort_clause| + field = format_field(sort_clause[:field]) + @query = @query.order(field => sort_clause[:ascending] ? :asc : :desc) + end @query end