J'ai un index unique sur plusieurs champs de ma base de données. Donc, si vous essayez d'appeler économiser sur un enregistrement en double, il augmente Activerecord :: relevéinvalid et affiche l'erreur MySQL. Existe-t-il un moyen de gérer cela dans les rails, soit en créant la contrainte unique, sinon avoir un message d'erreur pertinent lorsque cela se produit?
Heres la trace: P>
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'
3 Réponses :
Pouvez-vous modifier la requête en , vous pouvez envisager L'insertion code> La documentation est Ici . p> p> insérer ... sur la mise à jour de la touche en double ... code>. P>
Je pense que cela résoudrait quelque peu le problème, mais la requête SQL est générée automatiquement. Je pourrais le modifier, sauf que je veux que cela augmente une erreur, je ne peux qu'un que je puisse attraper et avoir un message, cela rend simplement le serveur dire 500 erreurs de serveur interne.
Vous pouvez ajouter une contrainte d'unicité à votre modèle afin que l'enregistrement revienne avec des erreurs et que ce soit invalide.
Par exemple (Rails 2): P>
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
Je sais que je peux le faire pour un seul champ, mais puis-je le faire pour plusieurs comme dans la mesure de possible, je peux vérifier si elles ont la même chose: email, nom, couleur préférée et travail. Il peut y avoir 5 personnes nommées John, mais un seul peut avoir john@example.com, orange et être programmeur. Cela a-t-il du sens?
Hé, j'ai mis à jour le message avec la réponse pour plusieurs attributs.
Bien que cela couvre la plupart des cas d'utilisation, il y a et a toujours été une condition de race dans Validates_uniqueness_of - elle n'arrête pas complètement les entrées en double grâce à la manière dont cela fonctionne.
C'est correct omar. Vous devriez toujours avoir un index unique dans MySQL sur (nom, âge, email) et il est préférable d'entourer vos mises à jour avec COMMEND..RESCUE..END.
begin Event.create!(:name => 'Ironman Lanzarote 2011') rescue ActiveRecord::RecordNotUnique => e # handle duplicate entry end This works for me under Rails 3.
Cela viole le principe du moindre étonnement et ne suit pas les conventions dans les rails.
Lorsque vous utilisez une configuration maître / esclave, vous rencontrerez des problèmes de dérivation (et les conditions de course résultantes), qui peuvent facilement être résolues à l'aide de cette approche, au lieu d'utiliser la validation unique des rails, ce qui pourrait le vérifier sur l'esclave.
C'est bon, mais je mettrais ce comportement sur une méthode modèle avec un nom descriptif.