Rails 3 AR: методы сохранения и обновления не сохраняют атрибуты, измененные в базе данных, но не объекты в памяти? - PullRequest
2 голосов
/ 09 июня 2011

Рассмотрим этот сценарий:

  1. butterfly = Butterfly.create (: color = 'blue')
  2. Butterfly.update_all (: color = 'red')

В этот момент, как и ожидалось, бабочка (в памяти) синего цвета, а соответствующий объект базы данных - красного цвета.Теперь попробуйте обновить запись базы данных

  1. butterfly.update_attributes (: size => 'big')

В результате атрибут size обновляется, но цветне.Мы остаемся в ситуации, когда даже после успешного сохранения или update_attributes база данных не соответствует объекту в памяти.На самом деле, даже butterfly.update_attribute(:color, 'blue') недостаточно для принудительного изменения базы данных!Единственное, что я вижу для принудительного изменения, - это сначала обновить атрибут на что-то другое (butterfly.update_attribute(:color,'anything')), а затем изменить его обратно на исходное значение.

Так ли должно быть?

1 Ответ

6 голосов
/ 09 июня 2011

Sort-оф.

Model.update_all выдает запрос на обновление непосредственно к базовой базе данных; он не обновляет экземпляры, которые у вас уже есть в памяти. Аналогично, instance.update_attributes только обновляет - он не извлекает данные из базы данных, поскольку предполагает, что экземпляр уже имеет самые последние значения атрибутов.

Этот обычно работает в Rails, экземпляры, как правило, недолговечны: они существуют только в рамках запроса, и в большинстве случаев с ними работают напрямую.

В описанной выше ситуации вам потребуется дополнительный шаг - Model#reload сделает то, что вы хотите:

# create our instance
@butterfly = Butterfly.create(color: 'blue') # => #<Butterfly id: 100, color: 'blue'>

Butterfly.update_all(color: 'red')

# We now have a mis-match between our instance and our database. Our instance 
# is still blue, but the database says it should be red. Reloading it...

@butterfly.reload # => #<Butterfly id: 100, color: 'red'>

# And we can now re-update our butterfly
@butterfly.update_attributes(size: 'big') # => #<Butterfly id: 100, color: 'red', size: 'big'>

Если вы используете update_all, неплохо бы посмотреть, возможно ли структурировать ваш код так, чтобы он происходил за до того, как вы загрузите экземпляры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...