postgres_upsert 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +13 -5
- data/.gitignore +1 -0
- data/.travis.yml +9 -0
- data/Gemfile.lock +93 -54
- data/README.md +106 -40
- data/Rakefile +4 -16
- data/bin/bundle +3 -0
- data/bin/rails +4 -0
- data/bin/rake +4 -0
- data/bin/setup +29 -0
- data/config.ru +4 -0
- data/config/application.rb +24 -0
- data/config/boot.rb +3 -0
- data/config/database.yml +22 -0
- data/config/environment.rb +5 -0
- data/config/environments/development.rb +41 -0
- data/config/environments/production.rb +79 -0
- data/config/environments/test.rb +42 -0
- data/config/locales/en.yml +23 -0
- data/config/routes.rb +56 -0
- data/config/secrets.yml +22 -0
- data/db/migrate/20150214192135_create_test_tables.rb +19 -0
- data/db/schema.rb +28 -0
- data/db/seeds.rb +7 -0
- data/lib/postgres_upsert.rb +8 -5
- data/lib/postgres_upsert/result.rb +11 -0
- data/lib/postgres_upsert/table_writer.rb +46 -0
- data/lib/postgres_upsert/writer.rb +25 -54
- data/postgres_upsert.gemspec +2 -2
- data/spec/pg_upsert_csv_spec.rb +87 -29
- data/spec/spec_helper.rb +5 -37
- metadata +42 -28
- data/lib/postgres_upsert/active_record.rb +0 -13
- data/spec/fixtures/2_col_binary_data.dat +0 -0
- data/spec/pg_upsert_binary_spec.rb +0 -35
- data/spec/spec.opts +0 -1
data/lib/postgres_upsert.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'active_record'
|
3
|
-
require 'postgres_upsert/active_record'
|
4
3
|
require 'postgres_upsert/writer'
|
4
|
+
require 'postgres_upsert/table_writer'
|
5
|
+
require 'postgres_upsert/result'
|
5
6
|
require 'rails'
|
6
7
|
|
7
|
-
|
8
|
+
module PostgresUpsert
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
class << self
|
11
|
+
def write class_or_table, path_or_io, options = {}
|
12
|
+
writer = class_or_table.is_a?(String) ?
|
13
|
+
TableWriter : Writer
|
14
|
+
writer.new(class_or_table, path_or_io, options).write
|
12
15
|
end
|
13
16
|
end
|
14
17
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module PostgresUpsert
|
2
|
+
# alternate version of PostgresUpsert::Writer which does not rely on AR table information. We
|
3
|
+
# we can use this model to upsert data into views, or tables not associated to rails models
|
4
|
+
class TableWriter < Writer
|
5
|
+
|
6
|
+
def initialize(table_name, source, options = {})
|
7
|
+
@table_name = table_name
|
8
|
+
super(nil, source, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def primary_key
|
14
|
+
@primary_key ||= begin
|
15
|
+
query = <<-sql
|
16
|
+
SELECT
|
17
|
+
pg_attribute.attname,
|
18
|
+
format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
|
19
|
+
FROM pg_index, pg_class, pg_attribute
|
20
|
+
WHERE
|
21
|
+
pg_class.oid = '#{@table_name}'::regclass AND
|
22
|
+
indrelid = pg_class.oid AND
|
23
|
+
pg_attribute.attrelid = pg_class.oid AND
|
24
|
+
pg_attribute.attnum = any(pg_index.indkey)
|
25
|
+
AND indisprimary
|
26
|
+
sql
|
27
|
+
|
28
|
+
pg_result = ActiveRecord::Base.connection.execute query
|
29
|
+
pg_result.each{ |row| return row['attname'] }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def column_names
|
34
|
+
@column_names ||= begin
|
35
|
+
query = "SELECT * FROM information_schema.columns WHERE TABLE_NAME = '#{@table_name}'"
|
36
|
+
pg_result = ActiveRecord::Base.connection.execute query
|
37
|
+
pg_result.map{ |row| row['column_name'] }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def quoted_table_name
|
42
|
+
@quoted_table_name ||= ActiveRecord::Base.connection.quote_table_name(@table_name)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module PostgresUpsert
|
2
|
-
|
3
2
|
class Writer
|
4
3
|
|
5
|
-
def initialize(
|
6
|
-
@
|
4
|
+
def initialize(klass, source, options = {})
|
5
|
+
@klass = klass
|
7
6
|
@options = options.reverse_merge({
|
8
7
|
:delimiter => ",",
|
9
|
-
:format => :csv,
|
10
8
|
:header => true,
|
11
9
|
:key_column => primary_key,
|
12
10
|
:update_only => false})
|
@@ -20,16 +18,15 @@ module PostgresUpsert
|
|
20
18
|
raise "Either the :columns option or :header => true are required"
|
21
19
|
end
|
22
20
|
|
23
|
-
csv_options =
|
21
|
+
csv_options = "DELIMITER '#{@options[:delimiter]}' CSV"
|
24
22
|
|
25
23
|
copy_table = @temp_table_name
|
26
|
-
|
27
24
|
columns_string = columns_string_for_copy
|
28
25
|
create_temp_table
|
29
26
|
|
30
27
|
ActiveRecord::Base.connection.raw_connection.copy_data %{COPY #{copy_table} #{columns_string} FROM STDIN #{csv_options}} do
|
31
28
|
|
32
|
-
while line =
|
29
|
+
while line = @source.gets do
|
33
30
|
next if line.strip.size == 0
|
34
31
|
ActiveRecord::Base.connection.raw_connection.put_copy_data line
|
35
32
|
end
|
@@ -37,46 +34,31 @@ module PostgresUpsert
|
|
37
34
|
|
38
35
|
upsert_from_temp_table
|
39
36
|
drop_temp_table
|
37
|
+
PostgresUpsert::Result.new(@insert_result, @update_result)
|
40
38
|
end
|
41
39
|
|
42
40
|
private
|
43
41
|
|
44
42
|
def primary_key
|
45
|
-
@primary_key
|
46
|
-
query = <<-sql
|
47
|
-
SELECT
|
48
|
-
pg_attribute.attname,
|
49
|
-
format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
|
50
|
-
FROM pg_index, pg_class, pg_attribute
|
51
|
-
WHERE
|
52
|
-
pg_class.oid = '#{@table_name}'::regclass AND
|
53
|
-
indrelid = pg_class.oid AND
|
54
|
-
pg_attribute.attrelid = pg_class.oid AND
|
55
|
-
pg_attribute.attnum = any(pg_index.indkey)
|
56
|
-
AND indisprimary
|
57
|
-
sql
|
58
|
-
|
59
|
-
pg_result = ActiveRecord::Base.connection.execute query
|
60
|
-
pg_result.each{ |row| return row['attname'] }
|
61
|
-
end
|
43
|
+
@klass.primary_key
|
62
44
|
end
|
63
45
|
|
64
46
|
def column_names
|
65
|
-
@column_names
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
47
|
+
@klass.column_names
|
48
|
+
end
|
49
|
+
|
50
|
+
def quoted_table_name
|
51
|
+
@klass.quoted_table_name
|
70
52
|
end
|
71
53
|
|
72
54
|
def get_columns
|
73
|
-
columns_list = @options[:columns]
|
74
|
-
if @options[:
|
55
|
+
columns_list = @options[:columns] ? @options[:columns].map(&:to_s) : []
|
56
|
+
if @options[:header]
|
75
57
|
#if header is present, we need to strip it from io, whether we use it for the columns list or not.
|
76
58
|
line = @source.gets
|
77
|
-
|
78
|
-
|
79
|
-
|
59
|
+
if columns_list.empty?
|
60
|
+
columns_list = line.strip.split(@options[:delimiter])
|
61
|
+
end
|
80
62
|
end
|
81
63
|
columns_list = columns_list.map{|c| @options[:map][c.to_s] } if @options[:map]
|
82
64
|
return columns_list
|
@@ -120,33 +102,17 @@ module PostgresUpsert
|
|
120
102
|
columns.size > 0 ? "\"#{columns.join('","')}\"" : ""
|
121
103
|
end
|
122
104
|
|
123
|
-
def quoted_table_name
|
124
|
-
@quoted_table_name ||= ActiveRecord::Base.connection.quote_table_name(@table_name)
|
125
|
-
end
|
126
|
-
|
127
105
|
def generate_temp_table_name
|
128
106
|
@temp_table_name = "#{@table_name}_temp_#{rand(1000)}"
|
129
107
|
end
|
130
108
|
|
131
|
-
def read_input_line
|
132
|
-
if @options[:format] == :binary
|
133
|
-
begin
|
134
|
-
return @source.readpartial(10240)
|
135
|
-
rescue EOFError
|
136
|
-
end
|
137
|
-
else
|
138
|
-
line = @source.gets
|
139
|
-
return line
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
109
|
def upsert_from_temp_table
|
144
110
|
update_from_temp_table
|
145
111
|
insert_from_temp_table unless @options[:update_only]
|
146
112
|
end
|
147
113
|
|
148
114
|
def update_from_temp_table
|
149
|
-
ActiveRecord::Base.connection.execute <<-SQL
|
115
|
+
@update_result = ActiveRecord::Base.connection.execute <<-SQL
|
150
116
|
UPDATE #{quoted_table_name} AS d
|
151
117
|
#{update_set_clause}
|
152
118
|
FROM #{@temp_table_name} as t
|
@@ -166,7 +132,7 @@ module PostgresUpsert
|
|
166
132
|
def insert_from_temp_table
|
167
133
|
columns_string = columns_string_for_insert
|
168
134
|
select_string = select_string_for_insert
|
169
|
-
ActiveRecord::Base.connection.execute <<-SQL
|
135
|
+
@insert_result = ActiveRecord::Base.connection.execute <<-SQL
|
170
136
|
INSERT INTO #{quoted_table_name} (#{columns_string})
|
171
137
|
SELECT #{select_string}
|
172
138
|
FROM #{@temp_table_name} as t
|
@@ -180,6 +146,7 @@ module PostgresUpsert
|
|
180
146
|
|
181
147
|
def create_temp_table
|
182
148
|
columns_string = select_string_for_create
|
149
|
+
verify_temp_has_key
|
183
150
|
ActiveRecord::Base.connection.execute <<-SQL
|
184
151
|
SET client_min_messages=WARNING;
|
185
152
|
DROP TABLE IF EXISTS #{@temp_table_name};
|
@@ -189,12 +156,16 @@ module PostgresUpsert
|
|
189
156
|
SQL
|
190
157
|
end
|
191
158
|
|
159
|
+
def verify_temp_has_key
|
160
|
+
unless @columns_list.include?(@options[:key_column].to_s)
|
161
|
+
raise "Expected a unique column '#{@options[:key_column]}' but the source data does not include this column. Update the :columns list or explicitly set the :key_column option.}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
192
165
|
def drop_temp_table
|
193
166
|
ActiveRecord::Base.connection.execute <<-SQL
|
194
167
|
DROP TABLE #{@temp_table_name}
|
195
168
|
SQL
|
196
169
|
end
|
197
170
|
end
|
198
|
-
|
199
|
-
|
200
171
|
end
|
data/postgres_upsert.gemspec
CHANGED
@@ -5,7 +5,7 @@ $:.unshift lib unless $:.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "postgres_upsert"
|
8
|
-
s.version = "
|
8
|
+
s.version = "4.0.0"
|
9
9
|
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
11
|
s.required_ruby_version = ">= 1.8.7"
|
@@ -26,8 +26,8 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.add_dependency "activerecord", '>= 3.0.0'
|
27
27
|
s.add_dependency "rails", '>= 3.0.0'
|
28
28
|
s.add_development_dependency "bundler"
|
29
|
-
s.add_development_dependency "rdoc"
|
30
29
|
s.add_development_dependency "pry-rails"
|
31
30
|
s.add_development_dependency "rspec", "~> 2.12"
|
31
|
+
s.add_development_dependency "rspec-rails", "~> 2.0"
|
32
32
|
end
|
33
33
|
|
data/spec/pg_upsert_csv_spec.rb
CHANGED
@@ -18,14 +18,14 @@ describe "pg_upsert from file with CSV format" do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should import from file if path is passed without field_map" do
|
21
|
-
|
21
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/comma_with_header.csv')
|
22
22
|
expect(
|
23
23
|
TestModel.first.attributes
|
24
24
|
).to include('data' => 'test data 1', 'created_at' => timestamp, 'updated_at' => timestamp)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "correctly handles delimiters in content" do
|
28
|
-
|
28
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/comma_with_header_and_comma_values.csv')
|
29
29
|
expect(
|
30
30
|
TestModel.first.attributes
|
31
31
|
).to include('data' => 'test, the data 1', 'created_at' => timestamp, 'updated_at' => timestamp)
|
@@ -33,39 +33,33 @@ describe "pg_upsert from file with CSV format" do
|
|
33
33
|
|
34
34
|
it "throws error if csv is malformed" do
|
35
35
|
expect{
|
36
|
-
|
37
|
-
}.to raise_error
|
38
|
-
end
|
39
|
-
|
40
|
-
it "throws error if the csv has mixed delimiters" do
|
41
|
-
expect{
|
42
|
-
TestModel.pg_upsert File.expand_path('spec/fixtures/tab_with_error.csv'), :delimiter => "\t"
|
36
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/comma_with_header_and_unquoted_comma.csv')
|
43
37
|
}.to raise_error
|
44
38
|
end
|
45
39
|
|
46
40
|
it "should import from IO without field_map" do
|
47
|
-
|
41
|
+
PostgresUpsert.write TestModel, File.open(File.expand_path('spec/fixtures/comma_with_header.csv'), 'r')
|
48
42
|
expect(
|
49
43
|
TestModel.first.attributes
|
50
44
|
).to include('data' => 'test data 1', 'created_at' => timestamp, 'updated_at' => timestamp)
|
51
45
|
end
|
52
46
|
|
53
47
|
it "should import with custom delimiter from path" do
|
54
|
-
|
48
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/semicolon_with_header.csv'), :delimiter => ';'
|
55
49
|
expect(
|
56
50
|
TestModel.first.attributes
|
57
51
|
).to include('data' => 'test data 1', 'created_at' => timestamp, 'updated_at' => timestamp)
|
58
52
|
end
|
59
53
|
|
60
54
|
it "should import with custom delimiter from IO" do
|
61
|
-
|
55
|
+
PostgresUpsert.write TestModel, File.open(File.expand_path('spec/fixtures/semicolon_with_header.csv'), 'r'), :delimiter => ';'
|
62
56
|
expect(
|
63
57
|
TestModel.first.attributes
|
64
58
|
).to include('data' => 'test data 1', 'created_at' => timestamp, 'updated_at' => timestamp)
|
65
59
|
end
|
66
60
|
|
67
61
|
it "should not expect a header when :header is false" do
|
68
|
-
|
62
|
+
PostgresUpsert.write(TestModel, File.open(File.expand_path('spec/fixtures/comma_without_header.csv'), 'r'), :header => false, :columns => [:id,:data])
|
69
63
|
|
70
64
|
expect(
|
71
65
|
TestModel.first.attributes
|
@@ -73,7 +67,7 @@ describe "pg_upsert from file with CSV format" do
|
|
73
67
|
end
|
74
68
|
|
75
69
|
it "should be able to map the header in the file to diferent column names" do
|
76
|
-
|
70
|
+
PostgresUpsert.write(TestModel, File.open(File.expand_path('spec/fixtures/tab_with_different_header.csv'), 'r'), :delimiter => "\t", :map => {'cod' => 'id', 'info' => 'data'})
|
77
71
|
|
78
72
|
expect(
|
79
73
|
TestModel.first.attributes
|
@@ -81,7 +75,7 @@ describe "pg_upsert from file with CSV format" do
|
|
81
75
|
end
|
82
76
|
|
83
77
|
it "should be able to map the header in the file to diferent column names with custom delimiter" do
|
84
|
-
|
78
|
+
PostgresUpsert.write(TestModel, File.open(File.expand_path('spec/fixtures/semicolon_with_different_header.csv'), 'r'), :delimiter => ';', :map => {'cod' => 'id', 'info' => 'data'})
|
85
79
|
|
86
80
|
expect(
|
87
81
|
TestModel.first.attributes
|
@@ -89,7 +83,7 @@ describe "pg_upsert from file with CSV format" do
|
|
89
83
|
end
|
90
84
|
|
91
85
|
it "should ignore empty lines" do
|
92
|
-
|
86
|
+
PostgresUpsert.write(TestModel, File.open(File.expand_path('spec/fixtures/tab_with_extra_line.csv'), 'r'), :delimiter => "\t")
|
93
87
|
|
94
88
|
expect(
|
95
89
|
TestModel.first.attributes
|
@@ -97,7 +91,7 @@ describe "pg_upsert from file with CSV format" do
|
|
97
91
|
end
|
98
92
|
|
99
93
|
it "should not create timestamps when the model does not include them" do
|
100
|
-
|
94
|
+
PostgresUpsert.write ReservedWordModel, File.expand_path('spec/fixtures/reserved_words.csv'), :delimiter => "\t"
|
101
95
|
|
102
96
|
expect(
|
103
97
|
ReservedWordModel.first.attributes
|
@@ -113,12 +107,12 @@ describe "pg_upsert from file with CSV format" do
|
|
113
107
|
|
114
108
|
it "should not violate primary key constraint" do
|
115
109
|
expect{
|
116
|
-
|
110
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/comma_with_header.csv')
|
117
111
|
}.to_not raise_error
|
118
112
|
end
|
119
113
|
|
120
114
|
it "should upsert (update existing records and insert new records)" do
|
121
|
-
|
115
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t"
|
122
116
|
|
123
117
|
expect(
|
124
118
|
TestModel.find(1).attributes
|
@@ -128,21 +122,33 @@ describe "pg_upsert from file with CSV format" do
|
|
128
122
|
).to eq("id"=>2, "data"=>"test data 2", "created_at" => timestamp, "updated_at" => timestamp)
|
129
123
|
end
|
130
124
|
|
125
|
+
it "should return updated and inserted results" do
|
126
|
+
result = PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t"
|
127
|
+
|
128
|
+
expect(
|
129
|
+
result.updated
|
130
|
+
).to eq(1)
|
131
|
+
|
132
|
+
expect(
|
133
|
+
result.inserted
|
134
|
+
).to eq(1)
|
135
|
+
end
|
136
|
+
|
131
137
|
it "should require columns option if no header" do
|
132
138
|
expect{
|
133
|
-
|
139
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/comma_without_header.csv'), :header => false
|
134
140
|
}.to raise_error("Either the :columns option or :header => true are required")
|
135
141
|
end
|
136
142
|
|
137
143
|
it "should clean up the temp table after completion" do
|
138
|
-
|
144
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t"
|
139
145
|
|
140
146
|
ActiveRecord::Base.connection.tables.should_not include("test_models_temp")
|
141
147
|
end
|
142
148
|
|
143
149
|
it "should gracefully drop the temp table if it already exists" do
|
144
150
|
ActiveRecord::Base.connection.execute "CREATE TEMP TABLE test_models_temp (LIKE test_models);"
|
145
|
-
|
151
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t"
|
146
152
|
|
147
153
|
expect(
|
148
154
|
TestModel.find(1).attributes
|
@@ -154,7 +160,7 @@ describe "pg_upsert from file with CSV format" do
|
|
154
160
|
|
155
161
|
it "should be able to copy using custom set of columns" do
|
156
162
|
ThreeColumn.create(id: 1, data: "old stuff", extra: "neva change!", created_at: original_created_at)
|
157
|
-
|
163
|
+
PostgresUpsert.write(ThreeColumn, File.open(File.expand_path('spec/fixtures/tab_only_data.csv'), 'r'), :delimiter => "\t", :columns => ["id", "data"])
|
158
164
|
|
159
165
|
expect(
|
160
166
|
ThreeColumn.first.attributes
|
@@ -167,8 +173,7 @@ describe "pg_upsert from file with CSV format" do
|
|
167
173
|
three_col = ThreeColumn.create(id: 1, data: "old stuff", extra: "neva change!")
|
168
174
|
file = File.open(File.expand_path('spec/fixtures/no_id.csv'), 'r')
|
169
175
|
|
170
|
-
|
171
|
-
ThreeColumn.pg_upsert(file, :key_column => "data")
|
176
|
+
PostgresUpsert.write(ThreeColumn, file, :key_column => "data")
|
172
177
|
expect(
|
173
178
|
three_col.reload.extra
|
174
179
|
).to eq("ABC: Always Be Changing.")
|
@@ -177,11 +182,29 @@ describe "pg_upsert from file with CSV format" do
|
|
177
182
|
it 'inserts records if the passed match column doesnt exist' do
|
178
183
|
file = File.open(File.expand_path('spec/fixtures/no_id.csv'), 'r')
|
179
184
|
|
180
|
-
|
185
|
+
PostgresUpsert.write(ThreeColumn, file, :key_column => "data")
|
181
186
|
expect(
|
182
187
|
ThreeColumn.last.attributes
|
183
|
-
).to include("
|
188
|
+
).to include("data" => "old stuff", "extra" => "ABC: Always Be Changing.")
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'allows key column to be a string or symbol' do
|
192
|
+
file = File.open(File.expand_path('spec/fixtures/no_id.csv'), 'r')
|
193
|
+
|
194
|
+
PostgresUpsert.write(ThreeColumn, file, :header => true, :key_column => :data)
|
195
|
+
expect(
|
196
|
+
ThreeColumn.last.attributes
|
197
|
+
).to include("data" => "old stuff", "extra" => "ABC: Always Be Changing.")
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'raises an error if the expected key column is not in data' do
|
201
|
+
file = File.open(File.expand_path('spec/fixtures/no_id.csv'), 'r')
|
202
|
+
|
203
|
+
expect{
|
204
|
+
PostgresUpsert.write(ThreeColumn, file, :header => true)
|
205
|
+
}.to raise_error (/Expected a unique column 'id'/)
|
184
206
|
end
|
207
|
+
|
185
208
|
end
|
186
209
|
|
187
210
|
context 'update only' do
|
@@ -189,9 +212,9 @@ describe "pg_upsert from file with CSV format" do
|
|
189
212
|
before(:each) do
|
190
213
|
TestModel.create(id: 1, data: "From the before time, in the long long ago", :created_at => original_created_at)
|
191
214
|
end
|
192
|
-
it 'will only update and not insert if insert_only flag is passed.' do
|
193
|
-
TestModel.pg_upsert File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t", :update_only => true
|
194
215
|
|
216
|
+
it 'will only update and not insert if insert_only flag is passed.' do
|
217
|
+
PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t", :update_only => true
|
195
218
|
expect(
|
196
219
|
TestModel.find(1).attributes
|
197
220
|
).to eq("id"=>1, "data"=>"test data 1", "created_at" => original_created_at , "updated_at" => timestamp)
|
@@ -201,6 +224,41 @@ describe "pg_upsert from file with CSV format" do
|
|
201
224
|
|
202
225
|
end
|
203
226
|
|
227
|
+
it 'will return the number of updated rows' do
|
228
|
+
a = PostgresUpsert.write TestModel, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t", :update_only => true
|
229
|
+
expect(
|
230
|
+
a.updated
|
231
|
+
).to eq(1)
|
232
|
+
|
233
|
+
expect(
|
234
|
+
a.inserted
|
235
|
+
).to eq(0)
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
context 'using table_name' do
|
241
|
+
it "should import from file if path is passed without field_map" do
|
242
|
+
PostgresUpsert.write TestModel.table_name, File.expand_path('spec/fixtures/comma_with_header.csv')
|
243
|
+
expect(
|
244
|
+
TestModel.first.attributes
|
245
|
+
).to include('data' => 'test data 1', 'created_at' => timestamp, 'updated_at' => timestamp)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should still report results" do
|
249
|
+
TestModel.create(data: "test data 1")
|
250
|
+
result = result = PostgresUpsert.write TestModel.table_name, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t"
|
251
|
+
|
252
|
+
expect(
|
253
|
+
result.updated
|
254
|
+
).to eq(1)
|
255
|
+
|
256
|
+
expect(
|
257
|
+
result.inserted
|
258
|
+
).to eq(1)
|
259
|
+
end
|
260
|
+
|
261
|
+
|
204
262
|
end
|
205
263
|
end
|
206
264
|
|