【问题标题】:hash.delete_if { |key, value| true } doesn't delete ... why?hash.delete_if { |键,值| true } 不删除...为什么?
【发布时间】:2023-03-30 18:02:01
【问题描述】:

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

放“之前:” + cache.inspect # cache.delete_if { |键,值| key.id == owner.id && key.class== owner.class } # 原代码行 cache.delete_if { |键,值| true } # 我的测试代码 放“之后:” + cache.inspect

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

我的问题是 cache.delete_if 不会删除任何东西,即使它总是评估为真。我只是不明白为什么......真的尝试了很多。这只是缓存哈希的问题。但我真的找不到关于那个特定哈希的任何特别之处。

缓存是用那个方法创建的:

def cached_owned_tag_list_on(上下文) variable_name = "@owned_#{context}_list" 缓存 = instance_variable_get(variable_name) || instance_variable_set(variable_name, {}) 结尾

完整代码可以在这里查看(见第60行):http://github.com/mbleigh/acts-as-taggable-on/blob/master/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb#L60

更进一步

当我在delete_if 之前执行rehash 时,它可以工作。什么可以“破坏”散列,在任何删除工作之前都需要重新散列?

【问题讨论】:

    标签: ruby-on-rails ruby hash


    【解决方案1】:

    来自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 被改变了。为什么会这样?嗯,很明显的原因是对象被创建,然后放入散列,然后保存(分配给它一个id 并更改了它的散列)。

    另外,这还有一个不好的后果:由于所有这些新创建的对象的哈希都是nil的哈希,如果有多个未保存的对象添加到哈希中,它们都会占用同一个槽,并试图用其他一些未保存的对象索引散列将返回废话。

    【讨论】:

    • 直到不散列 AR 模型。非常甜蜜的答案。
    【解决方案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
    => {}
    

    【讨论】:

    • cache.class.to_s 告诉我它是一个哈希。这真的很奇怪。
    • 试试cache.class.ancestors,里面有什么混入的吗? Rails 有时会改变一些事情,例如,它的哈希值对字符串/符号访问无关紧要,而 ActiveSupport 带有一个完整的 OrderedHash 类。
    【解决方案3】:

    可能是acts_as_taggable_on的一个bug,你可以填个bug报告。

    【讨论】:

    • 是的,也许……也可能……但这就是我想找出并解决的问题;-)
    猜你喜欢
    • 2019-03-27
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    • 2014-07-18
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    相关资源
    最近更新 更多