Skip to content

Commit

Permalink
Merge pull request #70 from manuquentin/allow_custom_attribute
Browse files Browse the repository at this point in the history
Allow to upsert on custom field
  • Loading branch information
olleolleolle authored Apr 25, 2018
2 parents f5570ef + 5e6e99d commit 488d69a
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 3 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ class Account < ApplicationRecord
end
```

Custom index can be handled with a Hash containing a literal key :

```ruby
class Account < ApplicationRecord
upsert_keys literal: 'md5(my_long_field)'
end
```

## Tests

Make sure to have an upsert_test database:
Expand Down
2 changes: 1 addition & 1 deletion lib/active_record_upsert/active_record/persistence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def upsert_keys(*keys)
options = keys.extract_options!
keys = keys.first if keys.size == 1 # support single string/symbol, multiple string/symbols, and array
return if keys.nil?
@_upsert_keys = Array(keys).map(&:to_s)
@_upsert_keys = Array(keys)
@_upsert_options = options
end

Expand Down
4 changes: 3 additions & 1 deletion lib/active_record_upsert/arel/crud.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
module Arel
module Crud
def compile_upsert(upsert_keys, upsert_options, upsert_values, insert_values, wheres)
# Support non-attribute key (like `md5(my_attribute)``)
target = self[upsert_keys.kind_of?(Hash) ? ::Arel::Nodes::SqlLiteral.new(upsert_keys[:literal]) : upsert_keys.join(',')]
on_conflict_do_update = OnConflictDoUpdateManager.new

on_conflict_do_update.target = self[upsert_keys.join(',')]
on_conflict_do_update.target = target
on_conflict_do_update.target_condition = upsert_options[:where]
on_conflict_do_update.wheres = wheres
on_conflict_do_update.set(upsert_values)
Expand Down
11 changes: 10 additions & 1 deletion spec/active_record/key_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ module ActiveRecord
end
end
context 'different ways of setting keys' do
let(:attrs) { {make: 'Ford', name: 'Focus'} }
let(:attrs) { {make: 'Ford', name: 'Focus', long_field: SecureRandom.uuid} }
before { Vehicle.create(attrs) }

it 'works with multiple symbol args' do
Vehicle.upsert_keys :make, :name
upserted = Vehicle.new(**attrs, wheels_count: 1)
Expand Down Expand Up @@ -85,6 +86,14 @@ module ActiveRecord
expect(upserted.wheels_count).to eq(1)
expect(upserted.id).to eq(v.id)
end
it 'works with a literal' do
v = Vehicle.create
Vehicle.upsert_keys literal: 'md5(long_field)'
upserted = Vehicle.new(id: v.id, long_field: attrs[:long_field])
upserted.upsert
expect(upserted.long_field).to eq(attrs[:long_field])
expect(upserted.id).to eq(v.id)
end
end

context 'when the record is not new' do
Expand Down
2 changes: 2 additions & 0 deletions spec/dummy/db/migrate/20160419103547_create_vehicles.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ def change
t.integer :wheels_count
t.string :name
t.string :make
t.string :long_field

t.timestamps

t.index [:make, :name], unique: true
t.index 'md5(long_field)', unique: true
end
end
end
13 changes: 13 additions & 0 deletions spec/dummy/db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ CREATE TABLE accounts (
--

CREATE SEQUENCE accounts_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
Expand Down Expand Up @@ -89,6 +90,7 @@ CREATE TABLE my_records (
--

CREATE SEQUENCE my_records_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
Expand Down Expand Up @@ -121,6 +123,7 @@ CREATE TABLE vehicles (
wheels_count integer,
name character varying,
make character varying,
long_field character varying,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
Expand All @@ -131,6 +134,7 @@ CREATE TABLE vehicles (
--

CREATE SEQUENCE vehicles_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
Expand Down Expand Up @@ -227,6 +231,13 @@ CREATE UNIQUE INDEX index_my_records_on_wisdom ON my_records USING btree (wisdom
CREATE UNIQUE INDEX index_vehicles_on_make_and_name ON vehicles USING btree (make, name);


--
-- Name: index_vehicles_on_md5_long_field; Type: INDEX; Schema: public; Owner: -
--

CREATE UNIQUE INDEX index_vehicles_on_md5_long_field ON vehicles USING btree (md5((long_field)::text));


--
-- PostgreSQL database dump complete
--
Expand All @@ -237,3 +248,5 @@ INSERT INTO "schema_migrations" (version) VALUES
('20160419103547'),
('20160419124138'),
('20160419124140');


1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'active_record'
require 'database_cleaner'
require 'securerandom'

# Configure Rails Environment
ENV['RAILS_ENV'] = 'test'
Expand Down

0 comments on commit 488d69a

Please sign in to comment.