ActiveRecord#save_only_valid_attributes
-
09-06-2019 - |
Вопрос
Я ищу вариацию на тему #save
Метод, который сохранит только атрибуты, которые не имеют прикрепленных к ним ошибок.Таким образом, модель может быть обновлена без действий в целом, и это все равно предотвратит сохранение неверных данных в базе данных.
Под «действительными атрибутами» я подразумеваю те атрибуты, которые дают ноль при вызове @model_instance.errors.on(:attribute)
У кого-нибудь есть идеи, как это сделать?
На данный момент у меня есть следующее:
def save_valid_attributes
valid?
update_atrtibutes attributes.inject({}){|k, v, m| m[k] = v unless errors_on(k.to_sym); m}
end
Это работает, если при назначении не выполняется обработка, что в моем случае есть.Например, у меня есть столбец базы данных «start_date» и определены два метода:
def nice_start_date=(startdate)
self.start_date = Chronic.parse(startdate) || startdate
end
def nice_start_date
self.start_date.to_s
end
Эти два метода позволяют мне правильно анализировать введенные пользователем даты с помощью Chronic перед сохранением.Итак, второй способ сделать это, по одному атрибуту за раз:
def save_valid_attributes(attrib)
valid?
attrib.each{|(k,v)| send("${k}=", v); save; reload)
end
Модель необходимо перезагружать каждый раз, поскольку, если одна из дат недействительна и не сохраняется, это не позволит сохранить все дальнейшие атрибуты.
Есть лучший способ сделать это?Я уверен, что это не редкая проблема в мире Rails, я просто не могу найти ничего во вселенной знаний Google.
Решение
Я не уверен, насколько вам повезет с этим, если вы не будете много возиться.
Независимо от того, насколько СУХОЙ, ОО и простой ваша структура делает вещи (а в данном случае - много =), вы все равно должны помнить, что она работает перед стандартной реляционной базой данных, в которой есть атомарные фиксации в качестве одной из ее функций. определение функции.Он разработан с нуля, чтобы гарантировать, что либо все ваши изменения будут зафиксированы, либо ни одного.
Фактически вы преодолеете эту стандартную функциональность с помощью чего-то, что на 100% противоречит тому, как был разработан Rail +.Это, скорее всего, приведет (как уже говорилось) к противоречивым данным.
Было сказано, что ...это всегда возможно.Я бы посмотрел на ручную проверку нужных вам атрибутов, а затем использовал встроенный метод. object.update_attribute_with_validation_skipping.
Удачи!
Другие советы
Вы можете перезаписать #save
так:
def save
errors.each do |attr, msg|
send("#{attr}=", send("#{attr}_was"))
end
super
end
Это приведет к сбросу всех атрибутов с ошибками, привязанными к их исходному значению.