SystemStackError when rescuing two unique constraints.
phallstrom opened this issue · comments
Sadly no fix for you, but if you try and rescue two unique constraints your app will crash with a SystemStackError.
spec/rescue_two_unique_constraints_spec.rb
require 'active_record'
require 'rescue_unique_constraint'
describe RescueUniqueConstraint do
before do
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
ActiveRecord::Schema.verbose = false
ActiveRecord::Schema.define(:version => 1) do
create_table :things do |t|
t.string :foo
t.string :bar
end
add_index :things, :foo, unique: true, name: "idx_things_on_foo_unique"
add_index :things, :bar, unique: true, name: "idx_things_on_bar_unique"
end
end
class Thing < ActiveRecord::Base
rescue_unique_constraint index: "idx_things_on_foo_unique", field: "foo"
rescue_unique_constraint index: "idx_things_on_bar_unique", field: "bar"
end
it "rescues unique constraint violations as activerecord errors" do
thing = Thing.create(foo: "1", bar: "2")
dupe = Thing.new(foo: "1", bar: "2")
expect(dupe.save).to eql false
expect(dupe.errors[:foo].first).to match /taken/
expect(dupe.errors[:bar].first).to match /taken/
end
end
Spec run output
F
Failures:
1) RescueUniqueConstraint rescues unique constraint violations as activerecord errors
Failure/Error:
define_method(:create_or_update_with_rescue) do
begin
create_or_update_without_rescue
rescue ActiveRecord::RecordNotUnique => e
case e.message
when /#{index}/ # Postgres
errors.add(field, :taken)
when /UNIQUE.*#{field}/ # SQLite
errors.add(field, :taken)
else
SystemStackError:
stack level too deep
# ./lib/rescue_unique_constraint.rb:11:in `block in rescue_unique_constraint'
.... the above line repeats many many many times....
# ./lib/rescue_unique_constraint.rb:13:in `block in rescue_unique_constraint'
# .../gems/activerecord-4.2.5/lib/active_record/persistence.rb:120:in `save'
# .../gems/activerecord-4.2.5/lib/active_record/validations.rb:37:in `save'
# .../gems/activerecord-4.2.5/lib/active_record/attribute_methods/dirty.rb:21:in `save'
# .../gems/activerecord-4.2.5/lib/active_record/transactions.rb:286:in `block (2 levels) in save'
# .../gems/activerecord-4.2.5/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
# .../gems/activerecord-4.2.5/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
# .../gems/activerecord-4.2.5/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
# .../gems/activerecord-4.2.5/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
# .../gems/activerecord-4.2.5/lib/active_record/transactions.rb:220:in `transaction'
# .../gems/activerecord-4.2.5/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
# .../gems/activerecord-4.2.5/lib/active_record/transactions.rb:286:in `block in save'
# .../gems/activerecord-4.2.5/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'
# .../gems/activerecord-4.2.5/lib/active_record/transactions.rb:285:in `save'
# .../gems/activerecord-4.2.5/lib/active_record/persistence.rb:34:in `create'
# ./spec/rescue_two_unique_constraints_spec.rb:25:in `block (2 levels) in <top (required)>'
Finished in 0.03207 seconds (files took 0.44959 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/rescue_two_unique_constraints_spec.rb:24 # RescueUniqueConstraint rescues unique constraint violations as activerecord errors
Thanks for pointing this out. We'll take a look.
Looks like this was fixed in #3, right?