lib/datashift/column_packer.rb in datashift-0.15.0 vs lib/datashift/column_packer.rb in datashift-0.16.0

- old
+ new

@@ -3,62 +3,126 @@ # Date :: Dec 2012 # License:: MIT # # Details:: Helper for creating consistent import/export format # of model's attributes/associations -# # -require 'exporter_base' -require 'csv' - module DataShift module ColumnPacker - - def text_delim - @text_delim ||= "\'" - end + include Delimiters - def text_delim=(x) - @text_delim = x - end - # Return opposite of text delim - "hello, 'barry'" => '"hello, "barry""' def escape_text_delim return '"' if text_delim == "\'" "\'" end - - + + + # Ensure a value is written to CSV correctly + # TODO - better ways ?? - see transcoding and String#encode + + def escape_for_csv(value) + text = value.to_s.gsub(text_delim, escape_text_delim()).gsub("\n", "\\n") + + text = "#{text_delim}#{text}#{text_delim}" if(text.include?(Delimiters::csv_delim)) + text + end + + + def to_headers( records, associations = nil, options = {} ) + return if( !records.first.is_a?(ActiveRecord::Base) || records.empty?) + + only = *options[:only] ? [*options[:only]] : nil + + headers =[] + + if associations + details_mgr = DataShift::MethodDictionary.method_details_mgrs[records.first.class] + + [*associations].each do |a| + + details_mgr.get_list(a).each do |md| + + next if(only && !only.include?( md.name.to_sym ) ) + + headers << "#{md.operator}" + + end + end if(details_mgr) + + else + + headers = records.first.class.columns.collect( &:name ) + end + + headers + end + + # Convert an AR instance to a single column - - def record_to_column(record, attribute_delim = Delimiters::csv_delim) - - csv_data = [] - record.serializable_hash.each do |name, value| - value = 'nil' if value.nil? - text = value.to_s.gsub(@text_delim, escape_text_delim()) - csv_data << "#{name.to_sym} => #{text}" + # e.g User : ":name = > 'tom', :role => 'developer'" + # + # OPTIONS + # with_only Specify (as symbols) columns for association types to export + # json: Export association data in single column in JSON format + # + def record_to_column(record, options = {}) + + return "" if(record.nil? || (record.respond_to?(:each) && record.empty?) ) + + with_only = *options[:with_only] ? [*options[:with_only]] : nil + + return record.to_json if(options[:json] && !with_only) # packs associations into single column + + if( record.respond_to?(:each) ) + + return "" if(record.empty?) + + data = [] + + record.each { |r| data << record_to_column(r, options); } + + if(options[:json]) + return data.to_json + else + return "#{data.join(Delimiters::multi_assoc_delim)}" + end + + else + + data = options[:json] ? {} : [] + + record.serializable_hash.each do |name, value| + next if(with_only && !with_only.include?( name.to_sym ) ) + + if(options[:json]) + data[name] = value + else + data << "#{name.to_sym} #{Delimiters::key_value_sep} #{value.to_s.gsub(text_delim, escape_text_delim)}" + end + end + + if(options[:json])# + return data.to_json + else + "#{Delimiters::attribute_list_start}#{data.join(Delimiters::multi_value_delim)}#{Delimiters::attribute_list_end}" + end + end - "#{csv_data.join(attribute_delim)}" + end - - + + # Convert an AR instance to a set of CSV columns def record_to_csv(record, options = {}) csv_data = record.serializable_hash.values.collect { |value| escape_for_csv(value) } [*options[:methods]].each { |x| csv_data << escape_for_csv(record.send(x)) if(record.respond_to?(x)) } if(options[:methods]) - + csv_data.join( Delimiters::csv_delim ) end - - def escape_for_csv(value) - text = value.to_s.gsub(@text_delim, escape_text_delim()) - - text = "#{@text_delim}#{text}#{@text_delim}" if(text.include?(Delimiters::csv_delim)) - text - end - + + end end