Module: PostgresCopy::ActsAsCopyTarget::CopyMethods

Defined in:
lib/postgres-copy/acts_as_copy_target.rb

Instance Method Summary collapse

Instance Method Details

#copy_from(path_or_io, options = {}) ⇒ Object

Copy data from a CSV that can be passed as a string (the file path) or as an IO object.

  • You can change the default delimiter passing delimiter: ” in the options hash

  • You can map fields from the file to different fields in the table using a map in the options hash

  • For further details on usage take a look at the README.md



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
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 44

def copy_from path_or_io, options = {}
  options = {:delimiter => ",", :format => :csv, :header => true}.merge(options)
  options_string = if options[:format] == :binary
                     "BINARY"
                   else
                     "DELIMITER '#{options[:delimiter]}' CSV"
                   end
  io = path_or_io.instance_of?(String) ? File.open(path_or_io, 'r') : path_or_io

  if options[:format] == :binary
    columns_list = options[:columns] || []
  elsif options[:header]
    line = io.gets
    columns_list = options[:columns] || line.strip.split(options[:delimiter])
  else
    columns_list = options[:columns]
  end

  table = if options[:table]
            connection.quote_table_name(options[:table])
          else
            quoted_table_name
          end

  columns_list = columns_list.map{|c| options[:map][c.to_s] } if options[:map]
  columns_string = columns_list.size > 0 ? "(\"#{columns_list.join('","')}\")" : ""
  connection.execute %{COPY #{table} #{columns_string} FROM STDIN #{options_string}}
  if options[:format] == :binary
    bytes = 0
    begin
      while line = io.readpartial(10240)
        connection.raw_connection.put_copy_data line
        bytes += line.bytesize
      end
    rescue EOFError
    end
  else
    while line = io.gets do
      next if line.strip.size == 0
      if block_given?
        row = line.strip.split(options[:delimiter])
        yield(row)
        line = row.join(options[:delimiter]) + "\n"
      end
      connection.raw_connection.put_copy_data line
    end
  end
  connection.raw_connection.put_copy_end
end

#copy_to(path = nil, options = {}) ⇒ Object

Copy data to a file passed as a string (the file path) or to lines that are passed to a block



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 10

def copy_to path = nil, options = {}
  options = {:delimiter => ",", :format => :csv, :header => true}.merge(options)
  options_string = if options[:format] == :binary
                     "BINARY"
                   else
                     "DELIMITER '#{options[:delimiter]}' CSV #{options[:header] ? 'HEADER' : ''}"
                   end

  if path
    raise "You have to choose between exporting to a file or receiving the lines inside a block" if block_given?
    connection.execute "COPY (#{self.all.to_sql}) TO #{sanitize(path)} WITH #{options_string}"
  else
    connection.execute "COPY (#{self.all.to_sql}) TO STDOUT WITH #{options_string}"
    while line = connection.raw_connection.get_copy_data do
      yield(line) if block_given?
    end
  end
  return self
end

#copy_to_string(options = {}) ⇒ Object

Copy all data to a single string



31
32
33
34
35
36
37
38
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 31

def copy_to_string options = {}
  data = ''
  self.copy_to(nil, options){|l| data << l }
  if options[:format] == :binary
    data.force_encoding("ASCII-8BIT")
  end
  data
end