plan
有很多plan_dates
。这是我控制台的一个简单示例
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
我认为Ruby从数据库中删除了记录但冻结了对象,所以它们仍然存在,尽管偶然:
a.plan_dates.each { |pd| puts pd.frozen? }
# => false
# => false
# => false
对于我销毁的第一个pd,我原以为true
。就像这样:
a.destroy
a.frozen?
# => true
用于迭代现有记录的方法是什么?像each_non_frozen
这样的东西。另外,对象实际上是如何从数组中删除的?我使用a.plan_date[0]
之类的特定plan_dates调用方法,并且我想要看到nil
或Sun, 07 Jun 2015 00:00:00 UTC +00:00
返回。
答案 0 :(得分: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