Учитывая модель, определенную следующим образом:
class Foo < ActiveRecord::Base
validates_uniqueness_of :bar
end
И служба, которая выполняет определенную операцию над ними:
class FooService
class << self
def run(bars_by_foo_id)
foos = Foo.find(bars_by_foo_id.keys).index_by(&:id)
ActiveRecord::Base.transaction do
bars_by_foo_id.each do |foo_id, bar|
foo = foos[foo_id]
foo.bar = bar
foo.save!
end
end
end
end
end
Когда я пытаюсь это сделать:
# Works
FooService.run({ 1: "a", 2: "b" })
# Breaks
FooService.run({ 1: "b", 2: "a" })
Первый вызов .run
назначает правильный bar
каждому Foo
, но второй прерывается, очевидно, потому что при попытке присвоить "b"
первому Foo
это значение не является уникальнымбольше.
Я пытался:
def run(bars_by_foo_id)
Foo.update(
bars_by_foo_id.keys,
bars_by_foo_id.values.map do |bar|
{ bar: bar }
end
)
end
Но, видимо, это только делает несколько отдельных обновлений и все еще ломается.
Каков был бы правильный способ достичь этого?Могу ли я сделать это в одном выражении SQL?У меня нет уникального ограничения в моей базе данных, только в моей модели.