2015-06-07 2 views
0

A plan имеет много plan_dates. Это тривиальный пример из моей консолиRuby destroy не работает? Или объекты все еще присутствуют?

a = Plan.create 
a.plan_dates.create(ddate: Date.today) 
a.plan_dates.create(ddate: Date.today + 1.days) 
a.plan_dates.create(ddate: Date.today + 2.days) 
a.plan_dates.count 
# => 3 
a.plan_dates.each { |pd| puts pd.ddate } 
# => 2015-06-06 00:00:00 UTC 
# => 2015-06-07 00:00:00 UTC 
# => 2015-06-08 00:00:00 UTC 

Когда я уничтожить plan_date, count следит за ней, но each не:

a.plan_dates.find_by_ddate(Date.today.to_datetime).destroy 
a.plan_dates.count 
# => 2 
a.plan_dates.each { |pd| puts pd.ddate } 
# => 2015-06-06 00:00:00 UTC 
# => 2015-06-07 00:00:00 UTC 
# => 2015-06-08 00:00:00 UTC 
a.plan_dates[0].ddate 
# => Sat, 06 Jun 2015 00:00:00 UTC +00:00 
a.plan_dates[1].ddate 
# => Sun, 07 Jun 2015 00:00:00 UTC +00:00 
a.plan_dates[2].ddate 
# => Mon, 08 Jun 2015 00:00:00 UTC +00:00 

Я понимаю, что рубин удаляет записи из БД, но замерзает объекты, поэтому они все еще там, хотя между прочим:

a.plan_dates.each { |pd| puts pd.frozen? } 
# => false 
# => false 
# => false 

Я бы ожидал, что это будет true для первого э.р. что я уничтожил. Как и как:

a.destroy 
a.frozen? 
# => true 

Какой метод использовать для перебора только существующих записей? Что-то вроде each_non_frozen. Кроме того, как объект фактически удаляется из массива? Я вызываю методы с конкретными параметрами plan_dates, например a.plan_date[0], и я либо хочу увидеть nil, либо Sun, 07 Jun 2015 00:00:00 UTC +00:00.

ответ

2

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

a.plan_dates.find_by_ddate(Date.today.to_datetime).destroy 
# DELETE FROM "plan_dates" WHERE ... 
a.plan_dates.count 
# SELECT COUNT(*) FROM "plan_dates" WHERE ... 
a.plan_dates.each { |pd| puts pd.ddate } 

Как вы видите, первые две строки инициируют SQL-запросы. Но последнего нет! Он использует кешированный массив из предыдущего запроса до plan_dates.each. Подробнее об этом можно узнать в разделе справки по кешированию (3.1): ActiveRecord Associations.

Вот как вы заставляете ваш массив снова извлекать данные из базы данных:

a.plan_dates(true).each { |pd| puts pd.ddate } 
# => 2015-06-07 00:00:00 UTC 
# => 2015-06-08 00:00:00 UTC 

# another way, with the same effect: 
a.plan_dates.reload.each { |pd| puts pd.ddate } 

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

a.plan_dates.find_by_ddate(Date.today.to_datetime).destroy 
# you have initiated SQL SELECT here! 
# the result is not contained in initial array 

Это будет работать, как вы ожидаете называется с искателей Enumerable или Array, а затем ActiveRecord:

a.plan_dates.find{|i| i.ddate == Date.today}.destroy 
a.plan_dates.find{|i| i.ddate == Date.today}.frozen? # => true 
+0

Это было БОЛЬШОЕ объяснение! – james

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

  • Нет связанных вопросов^_^