Синтаксический анализ сообщения об ошибке не так уж и плох, но выглядит глупо. Предложение, с которым я столкнулся (не помню, где), которое кажется привлекательным, состоит в том, что в блоке спасения вы можете проверить базу данных, чтобы увидеть, есть ли на самом деле дублирующая запись. Если есть, то есть вероятность, что StatementInvalid из-за дубликата, и вы можете обработать его соответствующим образом. Если нет, то StatementInvalid должен быть из чего-то другого, и вы должны обращаться с ним по-другому.
Итак, основная идея, предполагая уникальный индекс для recipe.name
, как указано выше:
begin
recipe.save!
rescue ActiveRecord::StatementInvalid
if Recipe.count(:conditions => {:name => recipe.name}) > 0
# It's a duplicate
else
# Not a duplicate; something else went wrong
end
end
Я попытался автоматизировать эту проверку с помощью следующего:
class ActiveRecord::Base
def violates_unique_index?(opts={})
raise unless connection
unique_indexes = connection.indexes(self.class.table_name).select{|i|i.unique}
unique_indexes.each do |ui|
conditions = {}
ui.columns.each do |col|
conditions[col] = send(col)
end
next if conditions.values.any?{|c|c.nil?} and !opts[:unique_includes_nil]
return true if self.class.count(:conditions => conditions) > 0
end
return false
end
end
Так что теперь вы сможете использовать generic_record.violates_unique_index?
в своем блоке спасения, чтобы решить, как обрабатывать StatementInvalid.
Надеюсь, это полезно! Другие подходы?