postgres_upsert 4.0.0 → 5.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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGQ4YTc4MTFmYzBjYzE1MWY3ODI3NGQ5Yjc5Njk4Mjk2MGJlZjdhNg==
4
+ NmI3N2Q0NmE4M2E3NjcxNzQxOTA2MDQ5NzAzMTZlMzk1Y2QzNmNlZQ==
5
5
  data.tar.gz: !binary |-
6
- ZmNhNzkxNDg4NzhlOWFhYjRjMWNkZDI5ZTMyMGQwMjZlMmM2ZjI4NQ==
6
+ MjEwODZlMTFlOGIwNTk2NGE3Y2FjMThhYjM0ZDU1YTZkOTAzOWFlMA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODU0N2IzZmM4ZDc1ODgzYzZmMDM1YzEyNTgwN2Y3MWUyMjI0ZmIxNjIzMjEy
10
- M2YyOGFlZjRiM2MzMjcwMTU2MzZjM2IyNWExNWQ3YTFiMzk4ZDIzYWY0MzZi
11
- ZTNmNGUwMDAxZDQxNGUwYjI4MTk0MWU3OWYxZDYwMzE5YmU0YjE=
9
+ MjQ5NTI0MzAyOWM0NTU3MmI2ZjBmYjMzNWJkZTcyYTdiOWNjNTk4MDYxMTdi
10
+ NDY3ZmQwNjRiNjE0YjE0ZDgyYzU0N2Q1NzhhZTcxNjRmZThiNjUyZTJkMTkw
11
+ NjY0NDI2ODU1OWYyNjA3ZmVlY2EwODRiMzBmYTNhYzQxODQ2ODk=
12
12
  data.tar.gz: !binary |-
13
- ZTVmMDBkMmFjZDRkNzIwZjI0MDNhNWRkZjlkMjg4YWU2YTI1MGM4NDVjMWY4
14
- MzI2NDE2MzMwOWQzY2Y3N2UwMjYxZDY1YzE4YTJkMDc2ZDg1M2MyZGVlN2Uz
15
- NzA0YjQ1YWUyNTBjMDhmNDNmZTNmYTNkZjE4ZmY0YTk2YWYxNzY=
13
+ ZGIyNzNiZGUxOTNmZDVlNTQxMWRkNjk4OWYxZWUyNTQ2OTkzNGZlYzBjOGVj
14
+ NmY2NDNlZmZmNWYzZTEwZTEwZWEzMjAyYzE3ZGQyNjUyY2NjY2Q4NGFjODgw
15
+ MzY1ZjZlNjUwZjU4MmY3NDMwOGViMDhlNjJmZThhN2MyNjg3NGY=
data/.gitignore CHANGED
@@ -9,6 +9,8 @@
9
9
  /test/version_tmp/
10
10
  /tmp/
11
11
  /log
12
+ .DS_Store
13
+ */.Ds_Store
12
14
 
13
15
  ## Specific to RubyMotion:
14
16
  .dat*
@@ -1,9 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.1.0
4
- - jruby-18mode
5
- - jruby-19mode
6
4
  - rbx-2
7
5
  - ruby-head
8
- - jruby-head
9
- - ree
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- postgres_upsert (4.0.0)
4
+ postgres_upsert (5.0.0)
5
5
  activerecord (>= 3.0.0)
6
- pg (~> 0.17.0)
6
+ pg (>= 0.17.0)
7
7
  rails (>= 3.0.0)
8
8
 
9
9
  GEM
@@ -49,9 +49,8 @@ GEM
49
49
  coderay (1.1.0)
50
50
  diff-lcs (1.1.3)
51
51
  erubis (2.7.0)
52
- globalid (0.3.3)
52
+ globalid (0.3.5)
53
53
  activesupport (>= 4.1.0)
54
- hike (1.2.3)
55
54
  i18n (0.7.0)
56
55
  json (1.8.2)
57
56
  loofah (2.0.1)
@@ -59,13 +58,12 @@ GEM
59
58
  mail (2.6.3)
60
59
  mime-types (>= 1.16, < 3)
61
60
  method_source (0.8.2)
62
- mime-types (2.4.3)
61
+ mime-types (2.6.1)
63
62
  mini_portile (0.6.2)
64
63
  minitest (5.5.1)
65
- multi_json (1.10.1)
66
64
  nokogiri (1.6.6.2)
67
65
  mini_portile (~> 0.6.0)
68
- pg (0.17.1)
66
+ pg (0.18.2)
69
67
  pry (0.10.1)
70
68
  coderay (~> 1.1.0)
71
69
  method_source (~> 0.8.1)
@@ -120,18 +118,14 @@ GEM
120
118
  rspec-expectations (~> 2.99.0)
121
119
  rspec-mocks (~> 2.99.0)
122
120
  slop (3.6.0)
123
- sprockets (2.12.3)
124
- hike (~> 1.2)
125
- multi_json (~> 1.0)
121
+ sprockets (3.2.0)
126
122
  rack (~> 1.0)
127
- tilt (~> 1.1, != 1.3.0)
128
- sprockets-rails (2.2.4)
123
+ sprockets-rails (2.3.2)
129
124
  actionpack (>= 3.0)
130
125
  activesupport (>= 3.0)
131
126
  sprockets (>= 2.8, < 4.0)
132
127
  thor (0.19.1)
133
128
  thread_safe (0.3.4)
134
- tilt (1.4.1)
135
129
  tzinfo (1.2.2)
136
130
  thread_safe (~> 0.1)
137
131
 
data/README.md CHANGED
@@ -28,7 +28,7 @@ PostgresUpsert.write <class_or_table_name>, <io_object_or_file_path>[, options]
28
28
  options:
29
29
  - :delimiter - the string to use to delimit fields from the source data. Default is ","
30
30
  - :header => specifies if the file/io source contains a header row. Either :header option must be true, or :columns list must be passed. Default true
31
- - :key_column => the primary key or unique key column on your destination table, used to distinguish new records from existing records. Default is the primary_key of your destination table/model.
31
+ - :unique_key => the primary key or unique key column (or composite key columns) on your destination table, used to distinguish new records from existing records. Default is the primary_key of your destination table/model.
32
32
  - :update_only => when true, postgres_upsert will ONLY update existing records, and not insert new. Default is false.
33
33
 
34
34
  ## Examples
@@ -66,16 +66,23 @@ currently postgres_upsert detects and manages the default rails timestamp column
66
66
  * records that are in the destination table but not the source will not have their timestamps changed.
67
67
 
68
68
 
69
- ### Overriding the key_column
69
+ ### Overriding the unique_key
70
70
 
71
- By default postgres_upsert uses the primary key on your ActiveRecord table to determine if each record should be inserted or updated. You can override the column using the :key_field option:
71
+ By default postgres_upsert uses the primary key on your ActiveRecord table to determine if each record should be inserted or updated. You can override the column using the :unique_key option:
72
72
 
73
73
  ```ruby
74
- PostgresUpsert.write User "/tmp/users.csv", :key_column => ["external_twitter_id"]
74
+ PostgresUpsert.write User "/tmp/users.csv", :unique_key => ["external_twitter_id"]
75
75
  ```
76
76
 
77
77
  obviously, the field you pass must be a unique key in your database (this is not enforced at the moment, but will be)
78
78
 
79
+ If your source data does not contain the primary key, or an individual unique key, you can pass multiple columns in the unique_key option:
80
+
81
+ ```ruby
82
+ PostgresUpsert.write User "/tmp/users.csv", :unique_key => ["state_id_numer", "state_name"]
83
+ ```
84
+ As long as combined columns represent a unique value, row, we can successfully upsert.
85
+
79
86
  passing :update_only => true will ensure that no new records are created, but records will be updated.
80
87
 
81
88
  ### Insert/Update Counts
@@ -124,7 +131,7 @@ def insert_smart
124
131
  end
125
132
  end
126
133
  io = StringIO.new(csv_string)
127
- PostgresUpsert.write User io, key_column: "email"
134
+ PostgresUpsert.write User io, unique_key: "email"
128
135
  end
129
136
  puts time
130
137
  end
@@ -0,0 +1,9 @@
1
+ class CreateCompositeModelsTable < ActiveRecord::Migration
2
+ def change
3
+ create_table :composite_key_models do |t|
4
+ t.integer :comp_key_1
5
+ t.integer :comp_key_2
6
+ t.string :data
7
+ end
8
+ end
9
+ end
@@ -11,18 +11,33 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 20150214192135) do
14
+ ActiveRecord::Schema.define(version: 20150710162236) do
15
15
 
16
16
  # These are extensions that must be enabled in order to support this database
17
17
  enable_extension "plpgsql"
18
18
 
19
- # Could not dump table "reserved_word_models" because of following NoMethodError
20
- # undefined method `[]' for nil:NilClass
19
+ create_table "composite_key_models", force: :cascade do |t|
20
+ t.integer "comp_key_1"
21
+ t.integer "comp_key_2"
22
+ t.string "data"
23
+ end
21
24
 
22
- # Could not dump table "test_models" because of following NoMethodError
23
- # undefined method `[]' for nil:NilClass
25
+ create_table "reserved_word_models", force: :cascade do |t|
26
+ t.string "select", limit: 255
27
+ t.string "group", limit: 255
28
+ end
24
29
 
25
- # Could not dump table "three_columns" because of following NoMethodError
26
- # undefined method `[]' for nil:NilClass
30
+ create_table "test_models", force: :cascade do |t|
31
+ t.string "data", limit: 255
32
+ t.datetime "created_at"
33
+ t.datetime "updated_at"
34
+ end
35
+
36
+ create_table "three_columns", force: :cascade do |t|
37
+ t.string "data", limit: 255
38
+ t.string "extra", limit: 255
39
+ t.datetime "created_at"
40
+ t.datetime "updated_at"
41
+ end
27
42
 
28
43
  end
@@ -2,9 +2,22 @@ module PostgresUpsert
2
2
  class Result
3
3
  attr_reader :inserted, :updated
4
4
 
5
- def initialize(insert_result, update_result)
5
+ def initialize(insert_result, update_result, copy_result)
6
6
  @inserted = insert_result ? insert_result.cmd_tuples : 0
7
7
  @updated = update_result ? update_result.cmd_tuples : 0
8
+ @copied = copy_result ? copy_result.cmd_tuples : 0
9
+ end
10
+
11
+ def changed_rows
12
+ @inserted + @updated
13
+ end
14
+
15
+ def copied_rows
16
+ @copied
17
+ end
18
+
19
+ def updated_rows
20
+ @updated
8
21
  end
9
22
  end
10
23
  end
@@ -10,6 +10,10 @@ module PostgresUpsert
10
10
 
11
11
  private
12
12
 
13
+ def database_connection
14
+ ActiveRecord::Base.connection
15
+ end
16
+
13
17
  def primary_key
14
18
  @primary_key ||= begin
15
19
  query = <<-sql
@@ -4,17 +4,18 @@ module PostgresUpsert
4
4
  def initialize(klass, source, options = {})
5
5
  @klass = klass
6
6
  @options = options.reverse_merge({
7
- :delimiter => ",",
8
- :header => true,
9
- :key_column => primary_key,
7
+ :delimiter => ",",
8
+ :header => true,
9
+ :unique_key => [primary_key],
10
10
  :update_only => false})
11
+ @options[:unique_key] = Array.wrap(@options[:unique_key])
11
12
  @source = source.instance_of?(String) ? File.open(source, 'r') : source
12
13
  @columns_list = get_columns
13
14
  generate_temp_table_name
14
15
  end
15
16
 
16
17
  def write
17
- if @columns_list.empty?
18
+ if @columns_list.empty?
18
19
  raise "Either the :columns option or :header => true are required"
19
20
  end
20
21
 
@@ -24,21 +25,37 @@ module PostgresUpsert
24
25
  columns_string = columns_string_for_copy
25
26
  create_temp_table
26
27
 
27
- ActiveRecord::Base.connection.raw_connection.copy_data %{COPY #{copy_table} #{columns_string} FROM STDIN #{csv_options}} do
28
+ @copy_result = database_connection.raw_connection.copy_data %{COPY #{copy_table} #{columns_string} FROM STDIN #{csv_options}} do
28
29
 
29
30
  while line = @source.gets do
30
31
  next if line.strip.size == 0
31
- ActiveRecord::Base.connection.raw_connection.put_copy_data line
32
+ database_connection.raw_connection.put_copy_data line
32
33
  end
33
34
  end
34
35
 
35
36
  upsert_from_temp_table
36
37
  drop_temp_table
37
- PostgresUpsert::Result.new(@insert_result, @update_result)
38
+
39
+ summarize_results
38
40
  end
39
41
 
40
42
  private
41
43
 
44
+ def database_connection
45
+ @klass.connection
46
+ end
47
+
48
+ def summarize_results
49
+ result = PostgresUpsert::Result.new(@insert_result, @update_result, @copy_result)
50
+ expected_rows = @options[:update_only] ? result.updated_rows : result.copied_rows
51
+
52
+ if result.changed_rows != expected_rows
53
+ raise "#{expected_rows} rows were copied, but #{result.changed_rows} were upserted to destination table. Check to make sure your key is unique."
54
+ end
55
+
56
+ return result
57
+ end
58
+
42
59
  def primary_key
43
60
  @klass.primary_key
44
61
  end
@@ -93,7 +110,9 @@ module PostgresUpsert
93
110
 
94
111
  def select_string_for_create
95
112
  columns = @columns_list.map(&:to_sym)
96
- columns << @options[:key_column].to_sym unless columns.include?(@options[:key_column].to_sym)
113
+ @options[:unique_key].each do |key_component|
114
+ columns << key_component.to_sym unless columns.include?(key_component.to_sym)
115
+ end
97
116
  get_columns_string(columns)
98
117
  end
99
118
 
@@ -112,12 +131,12 @@ module PostgresUpsert
112
131
  end
113
132
 
114
133
  def update_from_temp_table
115
- @update_result = ActiveRecord::Base.connection.execute <<-SQL
134
+ @update_result = database_connection.execute <<-SQL
116
135
  UPDATE #{quoted_table_name} AS d
117
136
  #{update_set_clause}
118
137
  FROM #{@temp_table_name} as t
119
- WHERE t.#{@options[:key_column]} = d.#{@options[:key_column]}
120
- AND d.#{@options[:key_column]} IS NOT NULL;
138
+ WHERE #{unique_key_select("t", "d")}
139
+ AND #{unique_key_present("d")}
121
140
  SQL
122
141
  end
123
142
 
@@ -132,39 +151,48 @@ module PostgresUpsert
132
151
  def insert_from_temp_table
133
152
  columns_string = columns_string_for_insert
134
153
  select_string = select_string_for_insert
135
- @insert_result = ActiveRecord::Base.connection.execute <<-SQL
154
+ @insert_result = database_connection.execute <<-SQL
136
155
  INSERT INTO #{quoted_table_name} (#{columns_string})
137
156
  SELECT #{select_string}
138
157
  FROM #{@temp_table_name} as t
139
- WHERE NOT EXISTS
140
- (SELECT 1
141
- FROM #{quoted_table_name} as d
142
- WHERE d.#{@options[:key_column]} = t.#{@options[:key_column]})
143
- AND t.#{@options[:key_column]} IS NOT NULL;
158
+ WHERE NOT EXISTS
159
+ (SELECT 1
160
+ FROM #{quoted_table_name} as d
161
+ WHERE #{unique_key_select("t", "d")});
144
162
  SQL
145
163
  end
146
164
 
165
+ def unique_key_select(source, dest)
166
+ @options[:unique_key].map {|field| "#{source}.#{field} = #{dest}.#{field}"}.join(' AND ')
167
+ end
168
+
169
+ def unique_key_present(source)
170
+ @options[:unique_key].map {|field| "#{source}.#{field} IS NOT NULL"}.join(' AND ')
171
+ end
172
+
147
173
  def create_temp_table
148
174
  columns_string = select_string_for_create
149
175
  verify_temp_has_key
150
- ActiveRecord::Base.connection.execute <<-SQL
176
+ database_connection.execute <<-SQL
151
177
  SET client_min_messages=WARNING;
152
178
  DROP TABLE IF EXISTS #{@temp_table_name};
153
179
 
154
- CREATE TEMP TABLE #{@temp_table_name}
180
+ CREATE TEMP TABLE #{@temp_table_name}
155
181
  AS SELECT #{columns_string} FROM #{quoted_table_name} WHERE 0 = 1;
156
182
  SQL
157
183
  end
158
184
 
159
185
  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.}"
186
+ @options[:unique_key].each do |key_component|
187
+ unless @columns_list.include?(key_component.to_s)
188
+ raise "Expected a unique column '#{key_component}' but the source data does not include this column. Update the :columns list or explicitly set the unique_key option.}"
189
+ end
162
190
  end
163
191
  end
164
192
 
165
193
  def drop_temp_table
166
- ActiveRecord::Base.connection.execute <<-SQL
167
- DROP TABLE #{@temp_table_name}
194
+ database_connection.execute <<-SQL
195
+ DROP TABLE #{@temp_table_name}
168
196
  SQL
169
197
  end
170
198
  end
@@ -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 = "4.0.0"
8
+ s.version = "5.0.0"
9
9
 
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.required_ruby_version = ">= 1.8.7"
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.require_paths = ["lib"]
23
23
  s.summary = "A rubygem that integrates with ActiveRecord to insert/update large data sets into the database efficiently"
24
24
 
25
- s.add_dependency "pg", '~> 0.17.0'
25
+ s.add_dependency "pg", '>= 0.17.0'
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"
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "pg_upsert from file with CSV format" do
4
+ before(:each) do
5
+ ActiveRecord::Base.connection.execute %{
6
+ TRUNCATE TABLE composite_key_models;
7
+ SELECT setval('composite_key_models_id_seq', 1, false);
8
+ }
9
+ end
10
+
11
+ before do
12
+ DateTime.stub_chain(:now, :utc).and_return (DateTime.parse("2012-01-01").utc)
13
+ end
14
+
15
+ def timestamp
16
+ DateTime.now.utc
17
+ end
18
+
19
+ context 'composite_key_support' do
20
+ it 'inserts records if the passed match composite key doesnt exist' do
21
+ file = File.open(File.expand_path('spec/fixtures/composite_key_with_header.csv'), 'r')
22
+
23
+ PostgresUpsert.write(CompositeKeyModel, file, :unique_key => ["comp_key_1", "comp_key_2"])
24
+ expect(
25
+ CompositeKeyModel.last.attributes
26
+ ).to include("data" => "test data 2")
27
+ end
28
+
29
+ it 'updates records if the passed composite key exists' do
30
+ file = File.open(File.expand_path('spec/fixtures/composite_key_with_header.csv'), 'r')
31
+ existing = CompositeKeyModel.create(comp_key_1: 2, comp_key_2:3, data: "old stuff")
32
+
33
+ PostgresUpsert.write(CompositeKeyModel, file, :unique_key => ["comp_key_1", "comp_key_2"])
34
+
35
+ expect(
36
+ CompositeKeyModel.find_by({comp_key_1: 2, comp_key_2:3}).attributes
37
+ ).to include("data" => "test data 2")
38
+
39
+ expect(
40
+ CompositeKeyModel.find_by({comp_key_1: 1, comp_key_2:2}).attributes
41
+ ).to include("data" => "test data 1")
42
+ end
43
+
44
+ it 'fails if composite keys are not unique.' do
45
+ file = File.open(File.expand_path('spec/fixtures/composite_nonkey_with_header.csv'), 'r')
46
+ existing = CompositeKeyModel.create(comp_key_1: 1, comp_key_2:2, data: "old stuff")
47
+
48
+ expect{
49
+ PostgresUpsert.write(CompositeKeyModel, file, :unique_key => ["comp_key_1", "comp_key_2"])
50
+ }.to raise_error(/Check to make sure your key is unique/)
51
+ end
52
+
53
+ end
54
+
55
+
56
+ end
@@ -0,0 +1,4 @@
1
+ require 'postgres_upsert'
2
+
3
+ class CompositeKeyModel < ActiveRecord::Base
4
+ end
@@ -0,0 +1,3 @@
1
+ comp_key_1,comp_key_2,data
2
+ 1,2,test data 1
3
+ 2,3,test data 2
@@ -0,0 +1,3 @@
1
+ comp_key_1,comp_key_2,data
2
+ 1,2,test data 1
3
+ 1,2,test data 4
@@ -173,7 +173,7 @@ describe "pg_upsert from file with CSV format" do
173
173
  three_col = ThreeColumn.create(id: 1, data: "old stuff", extra: "neva change!")
174
174
  file = File.open(File.expand_path('spec/fixtures/no_id.csv'), 'r')
175
175
 
176
- PostgresUpsert.write(ThreeColumn, file, :key_column => "data")
176
+ PostgresUpsert.write(ThreeColumn, file, :unique_key => "data")
177
177
  expect(
178
178
  three_col.reload.extra
179
179
  ).to eq("ABC: Always Be Changing.")
@@ -182,7 +182,7 @@ describe "pg_upsert from file with CSV format" do
182
182
  it 'inserts records if the passed match column doesnt exist' do
183
183
  file = File.open(File.expand_path('spec/fixtures/no_id.csv'), 'r')
184
184
 
185
- PostgresUpsert.write(ThreeColumn, file, :key_column => "data")
185
+ PostgresUpsert.write(ThreeColumn, file, :unique_key => "data")
186
186
  expect(
187
187
  ThreeColumn.last.attributes
188
188
  ).to include("data" => "old stuff", "extra" => "ABC: Always Be Changing.")
@@ -191,7 +191,7 @@ describe "pg_upsert from file with CSV format" do
191
191
  it 'allows key column to be a string or symbol' do
192
192
  file = File.open(File.expand_path('spec/fixtures/no_id.csv'), 'r')
193
193
 
194
- PostgresUpsert.write(ThreeColumn, file, :header => true, :key_column => :data)
194
+ PostgresUpsert.write(ThreeColumn, file, :header => true, :unique_key => :data)
195
195
  expect(
196
196
  ThreeColumn.last.attributes
197
197
  ).to include("data" => "old stuff", "extra" => "ABC: Always Be Changing.")
@@ -247,7 +247,7 @@ describe "pg_upsert from file with CSV format" do
247
247
 
248
248
  it "should still report results" do
249
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"
250
+ result = PostgresUpsert.write TestModel.table_name, File.expand_path('spec/fixtures/tab_with_two_lines.csv'), :delimiter => "\t"
251
251
 
252
252
  expect(
253
253
  result.updated
@@ -258,7 +258,6 @@ describe "pg_upsert from file with CSV format" do
258
258
  ).to eq(1)
259
259
  end
260
260
 
261
-
262
261
  end
263
262
  end
264
263
 
@@ -4,6 +4,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
  require 'fixtures/test_model'
5
5
  require 'fixtures/three_column'
6
6
  require 'fixtures/reserved_word_model'
7
+ require 'fixtures/composite_key_model'
7
8
  require 'rspec'
8
9
  require 'rspec/rails'
9
10
  require 'rspec/autorun'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postgres_upsert
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Mitchell
@@ -14,14 +14,14 @@ dependencies:
14
14
  name: pg
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.17.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.17.0
27
27
  - !ruby/object:Gem::Dependency
@@ -139,6 +139,7 @@ files:
139
139
  - config/routes.rb
140
140
  - config/secrets.yml
141
141
  - db/migrate/20150214192135_create_test_tables.rb
142
+ - db/migrate/20150710162236_create_composite_models_table.rb
142
143
  - db/schema.rb
143
144
  - db/seeds.rb
144
145
  - lib/postgres_upsert.rb
@@ -146,10 +147,14 @@ files:
146
147
  - lib/postgres_upsert/table_writer.rb
147
148
  - lib/postgres_upsert/writer.rb
148
149
  - postgres_upsert.gemspec
150
+ - spec/composite_key_spec.rb
149
151
  - spec/fixtures/comma_with_header.csv
150
152
  - spec/fixtures/comma_with_header_and_comma_values.csv
151
153
  - spec/fixtures/comma_with_header_and_unquoted_comma.csv
152
154
  - spec/fixtures/comma_without_header.csv
155
+ - spec/fixtures/composite_key_model.rb
156
+ - spec/fixtures/composite_key_with_header.csv
157
+ - spec/fixtures/composite_nonkey_with_header.csv
153
158
  - spec/fixtures/no_id.csv
154
159
  - spec/fixtures/reserved_word_model.rb
155
160
  - spec/fixtures/reserved_words.csv
@@ -190,10 +195,14 @@ specification_version: 4
190
195
  summary: A rubygem that integrates with ActiveRecord to insert/update large data sets
191
196
  into the database efficiently
192
197
  test_files:
198
+ - spec/composite_key_spec.rb
193
199
  - spec/fixtures/comma_with_header.csv
194
200
  - spec/fixtures/comma_with_header_and_comma_values.csv
195
201
  - spec/fixtures/comma_with_header_and_unquoted_comma.csv
196
202
  - spec/fixtures/comma_without_header.csv
203
+ - spec/fixtures/composite_key_model.rb
204
+ - spec/fixtures/composite_key_with_header.csv
205
+ - spec/fixtures/composite_nonkey_with_header.csv
197
206
  - spec/fixtures/no_id.csv
198
207
  - spec/fixtures/reserved_word_model.rb
199
208
  - spec/fixtures/reserved_words.csv