hash.delete_if {| key,value | true}不删除...为什么?

时间:2010-10-30 01:21:25

标签: ruby-on-rails ruby hash

我正在处理acts_as_taggable_on插件,但有一些我无法理解的东西(即使它只是一个非常简单的代码行)。

puts "before: " + cache.inspect
# cache.delete_if { |key, value| key.id == owner.id && key.class == owner.class } # original code line
cache.delete_if { |key, value| true } # my test code
puts "after: " + cache.inspect

# output
before: {#<TaggableUser id: 1, name: nil>=>["dog"]}
after: {# TaggableUser id: 1, name: nil>=>["dog"]}

我的问题是cache.delete_if不会删除任何内容,即使它总是计算为true。我根本就不明白为什么......并且真的尝试了很多。这只是缓存哈希的问题。但我真的找不到任何特别的哈希值。

使用该方法创建缓存:

def cached_owned_tag_list_on(context)
  variable_name = "@owned_#{context}_list"
  cache = instance_variable_get(variable_name) || instance_variable_set(variable_name, {})
end

可在此处查看完整代码(请参阅第60行):http://github.com/mbleigh/acts-as-taggable-on/blob/master/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb#L60

更进一步

当我在rehash之前执行delete_if时。什么可以在任何删除工作之前以重新散列的方式“破坏”哈希?

3 个答案:

答案 0 :(得分:4)

来自rehash的文档:

 call-seq:
   hsh.rehash -> hsh

 Rebuilds the hash based on the current hash values for each key. If
 values of key objects have changed since they were inserted, this
 method will reindex <i>hsh</i>. 

因此,您的密钥(常规ActiveRecord实例)的哈希值从创建时起已更改。调查AR来源:

# File activerecord/lib/active_record/base.rb, line 1613
1613:       def hash
1614:         id.hash
1615:       end

所以,他们的身份被改变了。为什么会这样?好吧,显而易见的原因是对象被创建,然后被放入哈希,然后保存(给它分配id并更改其哈希)。

此外,这还有另一个不好的后果:由于所有新创建的对象的哈希都是nil的哈希,如果有多个未保存的对象添加到哈希,它们都将占用相同的槽,并且尝试使用其他未保存的对象索引哈希将返回无意义。

答案 1 :(得分:2)

您确定cacheHash吗?您描述的行为不正常。

$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]

>> h = {:a => 1, :b => 2}
=> {:b=>2, :a=>1}
>> h
=> {:b=>2, :a=>1}
>> h.delete_if {|k,v| v == 2}
=> {:a=>1}
>> h
=> {:a=>1}

>> h = {:a => 1, :b => 2}
=> {:b=>2, :a=>1}
>> h.delete_if {|k,v| true}
=> {}
>> h
=> {}

答案 2 :(得分:0)

也许这是acts_as_taggable_on的错误,您只需填写错误报告即可。