Module: BetterCsv

Defined in:
lib/better_csv.rb,
lib/better_csv/version.rb

Constant Summary collapse

OPTIONS =
[:split_by_comma]
VERSION =
"0.0.6"

Class Method Summary collapse

Class Method Details

.[](array) ⇒ Object



36
37
38
# File 'lib/better_csv.rb', line 36

def self.[] array
  escape(array).collect{|a| a.join(',')}.join("\n")
end

.build(array, options: []) ⇒ Object



32
33
34
# File 'lib/better_csv.rb', line 32

def self.build array, options: []
  escape(array, options: options).collect{|a| a.join(',')}.join("\n")
end

.escape(array, options: []) ⇒ Object



21
22
23
24
25
26
27
28
29
30
# File 'lib/better_csv.rb', line 21

def self.escape array, options: []
  case array
  when Array
    array.collect{|v| escape_row(v, options: options)}
  when Hash
    array.values.collect{|v| escape_row(v, options: options)}
  else
    [escape_row(array.to_s, options: options)]
  end
end

.escape_row(value, options: []) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/better_csv.rb', line 6

def self.escape_row value, options: []
  case value
  when Array
    value.collect{|v| "\"#{v.to_s.gsub(/"/,'\"')}\""}
  when Hash
    value.values.collect{|v| "\"#{v.to_s.gsub(/"/,'\"')}\""}
  else
    if options.include?(:split_by_comma) and value.to_s.include?(',')
      escape_row(value.to_s.split(',')) #TODO: split by only non escaped comma.
    else
      ["\"#{value.to_s.gsub(/"/,'\"')}\""]
    end
  end
end

.parse(str) ⇒ Object



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
97
# File 'lib/better_csv.rb', line 40

def self.parse str
  in_literal = false
  csv = Array.new
  
  line    = []
  token   = ""
  back    = ""
  current = ""
  first   = true
  str.each_char do |c|
    current = c
    if first
      back = current
      if c == '"'
        in_literal = true
      elsif c == ','
        line << ""
      else
        token << c
      end
      first = false
      next
    end

    in_literal = !in_literal if current == '"' and not back == '\\' 

    if current == ',' and not in_literal
      line << token
      token = ""
      next
    end

    if current == "\n" and not in_literal
      line << token
      csv  << line
      token = ""
      yield(line) if block_given?
      line = Array.new
      next
    end
    
    token << c unless current == '"' and not back == '\\'
    back = current
  end
  
  if token.size > 0
    line << token
    yield(line) if block_given?
  elsif current == ','
    line << ''
  end
  csv << line if line.size > 0
  
  return csv
rescue => e
  STDERR.puts e
  STDERR.puts e.backtrace
end