У меня есть следующее в моем файле миграции
def self.up
create_table :payment_agreements do |t|
t.boolean :automatic, :default => true, :null => false
t.string :payment_trigger_on_order
t.references :supplier
t.references :seller
t.references :product
t.timestamps
end
end
Я хочу удостовериться, что, если product_id указан, это уникально, но я также хочу позволить пустой указатель, таким образом, у меня есть следующее в моей модели:
validates :product_id,
:uniqueness => true,
:allow_nil => true
Работает отлично, но я должен затем добавить индекс к файлу миграции
add_index :payment_agreements, :product_id, :unique => true
Очевидно, это выдаст исключение, когда два нулевых значения будут вставлены для product_id. Я мог просто опустить индекс в миграции, но затем существует шанс, что я получу два PaymentAgreements с тем же product_id как показано здесь: Параллелизм и целостность
Мой вопрос - то, что является лучшим / наиболее распространенный способ иметь дело с этой проблемой
Некоторые основные системы баз данных не позволяют уникальному индексу содержать несколько NULL: уникальность применяется как к NULL, так и к не-NULL. Существуют способы обойти это на уровне базы данных (например, триггеры или вычисляемый столбец; см. текст ссылки).
Можно решить эту проблему на уровне приложения и ввести валидацию, которая проверяет уникальность, если product_id
не является null.
validate :enforce_unique_product_id
def enforce_unique_product_id
if (!self.product_id.nil? &&
PaymentAgreement.exists?(:conditions=>['product_id = ?', self.product_id]))
errors.add_to_base('There is already an agreement with product id " +
self.product_id)
end
end
(Обновление: Как указал zed_0xff, MySql допускает несколько NULL в индексе UNIQUE в наиболее часто используемых хранилищах).
это зависит от вашего сервера db. что касается mysql:
Индекс UNIQUE создает ограничение такое, что все значения в индексе должны быть разными. Ошибка возникает, если вы пытаетесь добавить новую строку со значением ключа. которое совпадает с существующим. Этот ограничение не применяется к NULL за исключением хранилища BDB движка. Для других механизмов индекс UNIQUE индекс UNIQUE допускает несколько значений NULL для столбцов, которые могут содержать NULL.