如何在rails上使ruby处理来自MySQL的重复记录错误

loo*_*non 10 ruby mysql ruby-on-rails insert unique-constraint

我的数据库上有多个字段的唯一索引.因此,如果您尝试在重复记录上调用save,它会引发ActiveRecord :: StatementInvalid并显示mysql错误.有没有办法通过创建唯一约束来在rails中处理这个问题,或者在发生这种情况时让它返回相关的错误消息?

继承人追踪:

ActiveRecord::StatementInvalid: Mysql::Error: Duplicate entry '2010-12-09-2-0-1-1' for key 2: INSERT INTO `entries` (`rejected_at`, `created_at`, `comments`, `overtime`, `submitted_at`, `updated_at`, `time`, `approved`, `day`, `user_id`, `approved_at`, `job_id`, `submitted`, `rejected`) VALUES(NULL, '2010-12-09 21:50:46', NULL, 0, NULL, '2010-12-09 21:50:46', 2.0, NULL, '2010-12-09', 1, NULL, 1, NULL, NULL)
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:219:in `log'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:319:in `execute'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:259:in `insert_sql'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:329:in `insert_sql'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:44:in `insert_without_query_dirty'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:18:in `insert'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/base.rb:2901:in `create_without_timestamps'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/timestamp.rb:53:in `create_without_callbacks'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/callbacks.rb:266:in `create'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/base.rb:2867:in `create_or_update_without_callbacks'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/callbacks.rb:250:in `create_or_update'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/base.rb:2538:in `save_without_validation'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/validations.rb:1078:in `save_without_dirty'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/dirty.rb:79:in `save_without_transactions'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `send'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `with_transaction_returning_status'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/transactions.rb:182:in `transaction'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
 from /home/cmatthews/src/cannon/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save'
Run Code Online (Sandbox Code Playgroud)

小智 14

begin
  Event.create!(:name => 'Ironman Lanzarote 2011')
rescue ActiveRecord::RecordNotUnique => e
  # handle duplicate entry 
end
Run Code Online (Sandbox Code Playgroud)

这在Rails 3下适合我.

  • 使用主/从设置时,您会遇到漂移问题(以及由此产生的竞争条件),可以使用此方法轻松解决,而不是使用rails的唯一验证(可在从站上对其进行检查)。 (2认同)

Pan*_*kos 4

您可以向模型添加唯一性约束,以便记录返回时出现错误并且无效。

例如(Rails 2):

class User < ActiveRecord::Base
  validates_uniqueness_of :email, :scope => [:name, :age]
end
Run Code Online (Sandbox Code Playgroud)

或(轨道 3)

class User < ActiveRecord::Base
  validates :email, :uniqueness => {:scope => [:name, :age]}
end
Run Code Online (Sandbox Code Playgroud)

这应该会产生以下结果:

user1 = User.create :email => "one@example.com", :name => "one", :age => 20
user2 = User.create :email => "one@example.com", :name => "one", :age => 20
user2.valid? # false
Run Code Online (Sandbox Code Playgroud)

  • 虽然这涵盖了大多数用例,但 validates_uniqueness_of 中始终存在竞争条件 - 由于其工作方式,它并不能完全阻止重复条目。 (6认同)