如何从字符串而不是文件使用Rails postgresql连接raw.put_copy_data

时间:2015-01-30 05:54:42

标签: ruby-on-rails ruby postgresql

我通常使用以下导入模块将数据复制到rails中的postgres数据库中。

在这种情况下,我正在上传一个准备好接受postgres copy命令的文件。

module Import #< ActiveRecord::Base
  class Customer
  include ActiveModel::Model
  include EncodingSupport

  attr_accessor :file

  validates :file, :presence => true

  def process file=nil
    file ||= @file.tempfile
    ActiveRecord::Base.connection.execute('truncate customers')
    conn = ActiveRecord::Base.connection_pool.checkout
    raw  = conn.raw_connection
    raw.exec("COPY customers FROM STDIN WITH (FORMAT CSV, DELIMITER ',',  NULL ' ', HEADER true)")
    # open up your CSV file looping through line by line and getting the line into a format suitable for pg's COPY...
    data = file.open
    data::gets

    ticker = 0
    counter = 0
    success_counter = 0
    failed_records = []

    data.each_with_index do |line, index|
      raw.put_copy_data line
      counter += 1
    end
    # once all done...
    raw.put_copy_end
    while res = raw.get_result do; end # very important to do this after a copy
    ActiveRecord::Base.connection_pool.checkin(conn)
    return { :csv => false, :item_count => counter, :processed_successfully => counter, :errored_records => failed_records }
  end

我现在有另一个文件需要正确格式化,所以我有另一个模块将它从文本文件转换为csv文件并修剪掉不必要的内容。一旦准备就绪,我想将数据传递给上面的模块并让postgres将它带入数据库。

def pg_import file=nil
  file ||= @file.tempfile
  ticker = 0
  counter = 0
  col_order = [:warehouse_id, :customer_type_id, :pricelist_id]
  data = col_order.to_csv
  file.each do |line|
    line.strip!
    if item_line?(line)
      row = built_line
      data += col_order.map { |col| row[col] }.to_csv
    else
      line.empty?
    end
    ticker +=1
    counter +=1
    if ticker == 1000
      p counter
      ticker = 0
    end

  end

  pg_import data

end

我的问题是'process'方法将数据返回为

"warehouse_id,customer_type_id,pricelist_id\n201,A01,0AA\n201,A02,0AC

这意味着当我将它传递给pg_import时,我无法迭代数据。因为它希望它采用以下格式。

[0] "201,A01,0AA\r\n", [1] "201,A02,0AC\r\n", [2] "201,A03,oAE\r\n"

我可以使用什么命令转换字符串数据,以便我可以在

中迭代它

data.each_with_index do |line, index| raw.put_copy_data line counter += 1 end

...

可能有一个非常简单的解决方案,但只是期望在没有文件迭代的情况下无法使用put_copy_data ...

1 个答案:

答案 0 :(得分:0)

在循环之前和之内通过此过程解决了这个问题。

data = CSV.parse(data)
data.shift

data.each_with_index do |line, index|
  line = line.to_csv
  raw.put_copy_data line
  counter += 1
end

使用csv将字符串转换为数组数组。转移摆脱标题行。这允许我迭代数组。获取一个数组并将该数组从数组转换回csv字符串,然后将其传递到数据库中。