diff --git a/lib/rails_admin/support/csv_converter.rb b/lib/rails_admin/support/csv_converter.rb index 373c74fd94..3a5b06671c 100644 --- a/lib/rails_admin/support/csv_converter.rb +++ b/lib/rails_admin/support/csv_converter.rb @@ -3,9 +3,10 @@ module RailsAdmin class CSVConverter - def initialize(objects = [], schema = {}) + def initialize(objects = [], schema = nil) @fields = [] @associations = [] + schema ||= {} return self if (@objects = objects).blank? @@ -13,12 +14,13 @@ def initialize(objects = [], schema = {}) @abstract_model = RailsAdmin::AbstractModel.new(@model) @model_config = @abstract_model.config @methods = [(schema[:only] || []) + (schema[:methods] || [])].flatten.compact - @fields = @methods.collect { |m| export_fields_for(m).first } + @fields = @methods.collect { |m| export_field_for(m) }.compact @empty = ::I18n.t('admin.export.empty_value_for_associated_objects') schema_include = schema.delete(:include) || {} @associations = schema_include.each_with_object({}) do |(key, values), hash| - association = association_for(key) + association = export_field_for(key) + next unless association&.association? model_config = association.associated_model_config abstract_model = model_config.abstract_model methods = [(values[:only] || []) + (values[:methods] || [])].flatten.compact @@ -28,7 +30,7 @@ def initialize(objects = [], schema = {}) model: abstract_model.model, abstract_model: abstract_model, model_config: model_config, - fields: methods.collect { |m| export_fields_for(m, model_config).first }, + fields: methods.collect { |m| export_field_for(m, model_config) }.compact, } hash end @@ -61,12 +63,8 @@ def to_csv(options = {}) private - def association_for(key) - export_fields_for(key).detect(&:association?) - end - - def export_fields_for(method, model_config = @model_config) - model_config.export.fields.select { |f| f.name == method } + def export_field_for(method, model_config = @model_config) + model_config.export.fields.detect { |f| f.name == method } end def generate_csv_string(options) diff --git a/spec/integration/actions/export_spec.rb b/spec/integration/actions/export_spec.rb index 9e1db15152..2e40e80ae0 100644 --- a/spec/integration/actions/export_spec.rb +++ b/spec/integration/actions/export_spec.rb @@ -92,6 +92,12 @@ end end + it 'does not break when nothing is checked' do + visit export_path(model_name: 'comment') + all('input[type="checkbox"]').each(&:uncheck) + expect { click_button 'Export to csv' }.not_to raise_error + end + context 'with csv format' do it 'exports with modified schema' do page.driver.post(export_path(model_name: 'player', schema: @non_default_schema, csv: true, all: true, csv_options: {generator: {col_sep: ','}})) diff --git a/spec/rails_admin/support/csv_converter_spec.rb b/spec/rails_admin/support/csv_converter_spec.rb index 9bb818983d..ba15e6a202 100644 --- a/spec/rails_admin/support/csv_converter_spec.rb +++ b/spec/rails_admin/support/csv_converter_spec.rb @@ -17,6 +17,28 @@ expect(RailsAdmin::CSVConverter.new(objects, schema).to_csv({})[2]).to match(/Number,Name/) end + describe '#generate_csv_header' do + let(:objects) { FactoryBot.create_list :player, 1 } + before do + RailsAdmin.config(Player) do + export do + field :number + field :name + end + end + end + + it 'does not break when non-existent fields are given' do + expect(RailsAdmin::CSVConverter.new(objects, {only: [:name, :foo], include: {bar: :baz}}).send(:generate_csv_header)). + to eq ["Name"] + end + + it 'does not break when non-association fields are given to :include' do + expect(RailsAdmin::CSVConverter.new(objects, {only: [:name, :foo], include: {name: :name}}).send(:generate_csv_header)). + to eq ["Name"] + end + end + describe '#to_csv' do before do RailsAdmin.config(Player) do