Ruby 销毁不起作用?或者物体仍然存在?
Ruby destroy is not working? Or objects still present?
一个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
。另外,对象实际上是如何从数组中删除的?我调用具有特定 plan_date 的方法,例如 a.plan_date[0]
,并且我希望看到 nil
或 Sun, 07 Jun 2015 00:00:00 UTC +00:00
返回。
首先,让我解释一下数组保留已销毁元素的行为。由于 rails 缓存机制,这种情况是可能的。
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
一个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
。另外,对象实际上是如何从数组中删除的?我调用具有特定 plan_date 的方法,例如 a.plan_date[0]
,并且我希望看到 nil
或 Sun, 07 Jun 2015 00:00:00 UTC +00:00
返回。
首先,让我解释一下数组保留已销毁元素的行为。由于 rails 缓存机制,这种情况是可能的。
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