Skip to content

Commit

Permalink
Add failsafe measures to CSVConverter
Browse files Browse the repository at this point in the history
Fixes #1685
  • Loading branch information
mshibuya committed Oct 14, 2021
1 parent 177f32a commit f2104b5
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 10 deletions.
18 changes: 8 additions & 10 deletions lib/rails_admin/support/csv_converter.rb
Expand Up @@ -3,22 +3,24 @@

module RailsAdmin
class CSVConverter
def initialize(objects = [], schema = {})
def initialize(objects = [], schema = nil)
@fields = []
@associations = []
schema ||= {}

return self if (@objects = objects).blank?

@model = objects.dup.first.class
@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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions spec/integration/actions/export_spec.rb
Expand Up @@ -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: ','}}))
Expand Down
22 changes: 22 additions & 0 deletions spec/rails_admin/support/csv_converter_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit f2104b5

Please sign in to comment.