Я понял это, вот решение.
Контроллер:
# GET /agreements/1/release
def release
@agreement.released_at = Time.now.utc
if @agreement.save
render json: {success: ["Agreement released."]}
else
render json: @agreement.errors, status: :unprocessable_entity
end
end
Модель:
class Agreement < ApplicationRecord
validate :released_agreement_cannot_be_released
def released_agreement_cannot_be_released
if released_at_was.present?
errors.add(:released_at, "already released")
end
end
end
Это не ответ непосредственно на Ваш вопрос, но некоторую дополнительную информацию.
При контакте с несколькими столбцами и проверке, являются ли все пустыми или каждый не является пустым, я обычно использую COALESCE()
- это кратко, читаемо и легко удобно в сопровождении, если список растет:
COALESCE(a, b, c, d) IS NULL -- True if all are NULL
COALESCE(a, b, c, d) IS NOT NULL -- True if any one is not null
Это может использоваться в Вашем триггере.
Я сделал что-то подобное в SQL Server, я не уверен, будет ли это работать непосредственно в MySQL, но:
ALTER TABLE tableName ADD CONSTRAINT constraintName CHECK ( (fieldA IS NOT NULL) OR (fieldB IS NOT NULL) );
По крайней мере, я полагаю, что это - синтаксис.
Однако имейте в виду, что Вы не можете создать проверочные ограничения через таблицы, можно только проверить столбцы в одной таблице.
@Sklivvz: Тестируя с MySQL 5.0.51a, я нахожу, что он анализирует ограничение CHECK, но не осуществляет его. Я могу вставить (ПУСТОЙ УКАЗАТЕЛЬ, ПУСТОЙ УКАЗАТЕЛЬ) без ошибки. Протестированный и MyISAM и InnoDB. Впоследствии использование ВЫСТАВОЧНОГО CREATE TABLE показывает, что ограничение CHECK не находится в определении таблицы, даже при том, что никакая ошибка не была дана, когда я определил таблицу.
Это соответствует руководству MySQL, в котором говорится: "Пункт ПРОВЕРКИ анализируется, но игнорируется всеми механизмами устройства хранения данных".
Таким образом для MySQL, необходимо было бы использовать триггер для осуществления этого правила. Единственная проблема состоит в том, что триггеры MySQL не имеют никакого способа повысить ошибку или прервать операцию ВСТАВКИ. Одна вещь, которую можно сделать в триггере для порождения ошибки, состоит в том, чтобы установить столбец NOT NULL в NULL.
CREATE TABLE foo (
FieldA INT,
FieldB INT,
FieldA_or_FieldB TINYINT NOT NULL;
);
DELIMITER //
CREATE TRIGGER FieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SET NEW.FieldA_or_FieldB = NULL;
ELSE
SET NEW.FieldA_or_FieldB = 1;
END IF;
END//
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
Вам также нужен подобный триггер ПЕРЕД ОБНОВЛЕНИЕМ.
Это - стандартный синтаксис для такого ограничения, но MySQL блаженно игнорирует ограничение впоследствии
ALTER TABLE `generic`
ADD CONSTRAINT myConstraint
CHECK (
`FieldA` IS NOT NULL OR
`FieldB` IS NOT NULL
)