Class: RailsAdmin::CSVConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_admin/support/csv_converter.rb

Instance Method Summary collapse

Constructor Details

#initialize(objects = [], schema = {}) ⇒ CSVConverter

Returns a new instance of CSVConverter.

[View source]

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rails_admin/support/csv_converter.rb', line 11

def initialize(objects = [], schema = {})
  return self if (@objects = objects).blank?

  @model = objects.first.class
  @abstract_model = RailsAdmin::AbstractModel.new(@model)
  @model_config = @abstract_model.config
  @methods = [(schema[:only] || []) + (schema[:methods] || [])].flatten.compact
  @fields = @model_config.export.fields.select{|f| @methods.include? f.name }
  @empty = ::I18n.t('admin.export.empty_value_for_associated_objects')
  @associations = {}

  (schema.delete(:include) || {}).each do |key, values|
    association = @model_config.export.fields.find{|f| f.name == key && f.association?}
    model_config = association.associated_model_config
    abstract_model = model_config.abstract_model
    model = abstract_model.model
    methods = [(values[:only] || []) + (values[:methods] || [])].flatten.compact
    fields = model_config.export.fields.select{|f| methods.include? f.name }

    @associations[key] = {
      :association => association,
      :model => model,
      :abstract_model => abstract_model,
      :model_config => model_config,
      :fields => fields
    }
  end
end

Instance Method Details

#to_csv(options) ⇒ Object

[View source]

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rails_admin/support/csv_converter.rb', line 40

def to_csv(options)
  options ||= {}
  return '' if @objects.blank?

  # encoding shenanigans first
  @encoding_from = if [nil, '', 'utf8', 'utf-8', 'UTF8', 'UTF-8'].include?(encoding = Rails.configuration.database_configuration[Rails.env]['encoding'])
    'UTF-8'
  else
    encoding
  end

  unless options[:encoding_to].blank?
    @encoding_to = options[:encoding_to]
    unless @encoding_to == @encoding_from
      require 'iconv'
      @iconv = (Iconv.new("#{@encoding_to}//TRANSLIT//IGNORE", @encoding_from) rescue (Rails.logger.error("Iconv cannot convert to #{@encoding_to}: #{$!}\nNo conversion will take place"); nil))
    end
  else
    @encoding_to = @encoding_from
  end

  csv_string = CSVClass.generate(options[:generator] ? options[:generator].symbolize_keys.delete_if {|key, value| value.blank? } : {}) do |csv|
    unless options[:skip_header]
      csv << @fields.map do |field|
        output(::I18n.t('admin.export.csv.header_for_root_methods', :name => field.label, :model => @abstract_model.pretty_name))
      end +
      @associations.map do |association_name, option_hash|
        option_hash[:fields].map do |field|
          output(::I18n.t('admin.export.csv.header_for_association_methods', :name => field.label, :association => option_hash[:association].label))
        end
      end.flatten
    end
    @objects.each do |o|


      csv << @fields.map do |field|
        output(field.with(:object => o).export_value)
      end +
      @associations.map do |association_name, option_hash|

        associated_objects = [o.send(association_name)].flatten.compact
        option_hash[:fields].map do |field|
          output(associated_objects.map{ |ao| field.with(:object => ao).export_value.presence || @empty }.join(','))
        end
      end.flatten
    end
  end

  # Add a BOM for utf8 encodings, helps with utf8 auto-detect for some versions of Excel.
  # Don't add if utf8 but user don't want to touch input encoding:
  # If user chooses utf8, he will open it in utf8 and BOM will disappear at reading.
  # But that way "English" users who don't bother and chooses to let utf8 by default won't get BOM added
  # and will not see it if Excel opens the file with a different encoding.
  csv_string = "\xEF\xBB\xBF#{csv_string.respond_to?(:force_encoding) ? csv_string.force_encoding('UTF-8') : csv_string}" if options[:encoding_to] == 'UTF-8'
  csv_string = ((@iconv ? @iconv.iconv(csv_string) : csv_string) rescue str) if @encoding_to =~ NON_ASCII_ENCODINGS # global conversion for non ASCII encodings
  [!options[:skip_header], @encoding_to, csv_string]
end