2015-05-06 2 views
2

Видимо, я видел allthosequestions с ответами вроде: «Использовать find_or_create_by/initialize_by(<cols>)».Как правильно вставить или обновить запись в рельсах?

И вопрос: «Это только я, или эти ответы немного« сломаны »?» Если вы запрашиваете вставку или обновление, это обычно означает, что записи должны быть уникальными: не должно существовать двух записей с совпадением <cols>. Следуя этим ответам, вы либо в конечном итоге получите дубликаты строк в базе данных, либо изредка будете иметь исключения (если уникальность выполняется с уникальным индексом).

Почему никто не предлагает такой путь?

begin 
    Counter.create(name: '...', value: 1) 
rescue ActiveRecord::RecordNotUnique 
    Counter.where(name: '...').update_all('value = value + 1') 
end 

И что это? Должен ли я пойти с find_or_create_by/initialize_by? Или я должен полагаться на уникальный индекс db? На боковой ноте я не могу придумать ни одного случая, когда хочется сделать вставку или обновление и в порядке с дублирующимися строками.

+0

Это риторический вопрос? –

+0

Разве это не удовлетворено, просто используя хорошую проверку? Помните, что концепция рельсов является условной конфигурацией. Зачем что-то усложнять, если нет необходимости? –

+1

@DavidHoelzer Поскольку проверки подвержены условиям гонки, поэтому определенная логика должна идти в базе данных. –

ответ

-1

Потому что begin...rescue не должен использоваться для этого.

begin...rescue есть для когда возникает ошибка.

Вот пример от Ruby Learning.

def inverse(x) 
    raise ArgumentError, 'Argument is not numeric' unless x.is_a? Numeric 
    1.0/x 
end 

Ваш пример повторяющейся записи на самом деле не «ошибка», так как это может произойти, когда дубликата данные передаются.

find_or_create_by элегантно обрабатывает оба случая, без понятия «условие ошибки».

+1

Но нарушение уникального ограничения в базе данных * есть * ошибка. Просто потому, что что-то является ошибкой на одном уровне, не означает, что она должна быть ошибкой на всех уровнях. BTW, 'find_or_create_by' - это просто' find_by (...) || создайте (...) ', поэтому он по-прежнему подвержен условиям гонки, [документация] (http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_create_by) даже рекомендует обернуть его в обработчик исключений, если требуется уникальность. –

Смежные вопросы