Как отловить исключение ActiveRecord :: RecordNotFound во время сохранения ()? - PullRequest
1 голос
/ 24 мая 2011

В моей базе данных есть таблица Users со столбцом Email.Я также создал индекс UNIQUE для столбца «Электронная почта», чтобы два пользователя не могли зарегистрировать один и тот же адрес электронной почты (примечание: пожалуйста, не предлагайте мне использовать validates_uniqueness_of, поскольку это то, чего я пытаюсь избежать).

Когда я запускаю свой тест RSpec, чтобы убедиться, что дубликат записи не может быть вставлен, я вижу следующую ошибку:

Failures:
  1) User should not allow duplicate email addresses
     Failure/Error: user2.save.should_not be_true
     ActiveRecord::RecordNotUnique:
       SQLite3::ConstraintException: column email is not unique: INSERT INTO "users" ("email", ... ) VALUES ( ... )
     # ./spec/models/user_spec.rb:26

Это хорошо, потому что это означает, что мой индекс UNIQUE действительно работает,Вопрос в том, как я могу обработать это исключение?Я хотел бы иметь возможность перехватить его, а затем добавить разумное сообщение в коллекцию ошибок модели.

Я попытался - безуспешно - используя rescue_from в контроллере следующим образом:

rescue_from 'ActiveRecord::RecordNotUnique' do |ex|
    raise 'Email must be unique'
end

Документы Rails API не содержат подсказок о том, как переопределить метод save () для добавления блока begin / rescue, поэтому мой вопрос таков: как я могу обработать исключение ActiveRecord :: RecordNotUnique, которое выдаетсяво время сохранения () затем пометьте модель как недействительную и добавьте разумное сообщение об ошибке в коллекцию ошибок модели?

Ответы [ 2 ]

3 голосов
/ 24 мая 2011
class User
...
def save
 super
 rescue 'ActiveRecord::RecordNotUnique' 
   logger.error($!.to_s) # or something like that.
 end
end

Вы можете перегрузить любое действие в своих моделях и просто вызвать super, чтобы выполнить определение унаследованного метода

В Rails API он не упоминается, потому что это особенность Ruby, а не только Rails.

0 голосов
/ 28 мая 2014

У меня была похожая проблема.У меня есть таблица с индексом, использующая несколько полей вверх, по которым таблица сортируется

в db / migrate

class CreateDids < ActiveRecord::Migration
  def change
    create_table :dids do |t|
      t.string :lada, null: false, limit: 3
      t.string :pre_did, null: false, limit: 4
      t.string :did, null: false, limit: 7
      t.boolean :uso_interno_ns, default: false, null: false

      t.timestamps
      t.integer :lock_version, null: false, default: 0
      t.index [:lada, :pre_did, :did], unique: true
    end
  end
end

Теперь,чтобы проверить уникальное сочетание полей в models / did.rb Я написал:

  validates :lada, presence: true, length: { within: 1..3 }, numericality: { only_integer: true}
  validates :pre_did, presence: true, length: { within: 1..4 }, numericality: { only_integer: true}
  validates :did, presence: true, length: { within: 4..7 }, numericality: { only_integer: true}
  validate do
    errors.add :base,I18n.t('dids.numero_menor_10') unless 10 == ( self.lada + self.pre_did + self.did ).size if self.lada and self.pre_did and self.did
  end

Но он не подтвердил дублированное сочетание полей (lada+ pre_did + did), поэтому в models / did.rb также написано:

def save
  begin
    super
  rescue ActiveRecord::RecordNotUnique => e
    errors.add(:base,I18n.t('dids.telefono_duplicado'))
    false
  end
end

def update( x )
  begin
    super x
  rescue ActiveRecord::RecordNotUnique => e
    errors.add(:base,I18n.t('dids.telefono_duplicado'))
    false
  end
end

Теперь в моем случае, если я не вернусь false после спасения это не работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...