Module: PostgresCopy::ActsAsCopyTarget::CopyMethods
- Defined in:
- lib/postgres-copy/acts_as_copy_target.rb
Instance Method Summary collapse
-
#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.
-
#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.
-
#copy_to_enumerator(options = {}) ⇒ Object
Create an enumerator with each line from the CSV.
-
#copy_to_string(options = {}) ⇒ Object
Copy all data to a single string.
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
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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 73 def copy_from path_or_io, = {} = {:delimiter => ",", :format => :csv, :header => true, :quote => '"'}.merge() = if [:format] == :binary "BINARY" else quote = [:quote] == "'" ? "''" : [:quote] null = .key?(:null) ? "NULL '#{[:null]}'" : '' "DELIMITER '#{[:delimiter]}' QUOTE '#{quote}' #{null} CSV" end io = path_or_io.instance_of?(String) ? File.open(path_or_io, 'r') : path_or_io if [:format] == :binary columns_list = [:columns] || [] elsif [:header] line = io.gets columns_list = [:columns] || line.strip.split([:delimiter]) else columns_list = [:columns] end table = if [:table] connection.quote_table_name([:table]) else quoted_table_name end columns_list = columns_list.map{|c| [:map][c.to_s] } if [:map] columns_string = columns_list.size > 0 ? "(\"#{columns_list.join('","')}\")" : "" connection.raw_connection.copy_data %{COPY #{table} #{columns_string} FROM STDIN #{}} do if [: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 = CSV.parse_line(line.strip, {:col_sep => [:delimiter]}) yield(row) next if row.all?{|f| f.nil? } line = CSV.generate_line(row, {:col_sep => [:delimiter]}) end connection.raw_connection.put_copy_data line end end 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
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 12 def copy_to path = nil, = {} = {:delimiter => ",", :format => :csv, :header => true}.merge() = if [:format] == :binary "BINARY" else "DELIMITER '#{[:delimiter]}' CSV #{[: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 #{}" else connection.raw_connection.copy_data "COPY (#{self.all.to_sql}) TO STDOUT WITH #{}" do while line = connection.raw_connection.get_copy_data do yield(line) if block_given? end end end return self end |
#copy_to_enumerator(options = {}) ⇒ Object
Create an enumerator with each line from the CSV. Note that using this directly in a controller response will perform very poorly as each line will get put into its own chunk. Joining every (eg) 100 rows together is much, much faster.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 38 def copy_to_enumerator(={}) buffer_lines = .delete(:buffer_lines) # Somehow, self loses its scope once inside the Enumerator scope = self.current_scope || self result = Enumerator.new do |y| scope.copy_to(nil, ) do |line| y << line end end if buffer_lines.to_i > 0 Enumerator.new do |y| result.each_slice(buffer_lines.to_i) do |slice| y << slice.join end end else result end end |
#copy_to_string(options = {}) ⇒ Object
Copy all data to a single string
60 61 62 63 64 65 66 67 |
# File 'lib/postgres-copy/acts_as_copy_target.rb', line 60 def copy_to_string = {} data = '' self.copy_to(nil, ){|l| data << l } if [:format] == :binary data.force_encoding("ASCII-8BIT") end data end |