Я бы определенно написал валидации для этого - проще предоставить пользователю хорошие сообщения об ошибках из валидаций.Я также хотел бы поддержать это с ограничением базы данных.Похоже, что проверочные ограничения действительно могут сделать эту работу.
Rails не имеет поддержки, которую я мог бы найти, поэтому вам нужно будет создать таблицу с raw sql.Вам также нужно изменить дампер схемы на :sql
, так как rails не сможет создать schema.rb
, который действительно описывает это.
Я написал эту миграцию
class CreateFoos < ActiveRecord::Migration
def change
execute <<SQL
CREATE TABLE foos (
id INTEGER PRIMARY KEY,
x_id INTEGER,
y_id INTEGER,
constraint xorit check( (x_id OR y_id) AND NOT(x_id AND y_id))
)
SQL
end
end
Затем в консоли rails
Foo.create(:x_id => 1, :y_id => 1) #=> SQLite3::ConstraintException
Как таковой, вы можете создать строку без установленных x_id и y_id.Вы можете изменить это, изменив ограничение,
(x_id IS NOT NULL OR y_id IS NOT NULL ) AND (x_id IS NULL OR y_id IS NULL)
, похоже, работает для меня