ruby-on-rails - Ruby 2.3.1 的 OpenStruct 问题

标签 ruby-on-rails ruby openstruct ruby-2.3

在 Ruby 2.1.5 和 2.2.4 中,创建新的 Collector 会返回正确的结果。

require 'ostruct'
module ResourceResponses
  class Collector < OpenStruct
    def initialize
      super
      @table = Hash.new {|h,k| h[k] = Response.new }
    end
  end

  class Response
    attr_reader :publish_formats, :publish_block, :blocks, :block_order
    def initialize
      @publish_formats = []
      @blocks = {}
      @block_order = []
    end
  end  
end

 > Collector.new
 => #<ResourceResponses::Collector>
 Collector.new.responses
 => #<ResourceResponses::Response:0x007fb3f409ae98 @block_order=[], @blocks=  {}, @publish_formats=[]>

当我升级到 Ruby 2.3.1 时,它开始返回 nil。

> Collector.new
=> #<ResourceResponses::Collector>
> Collector.new.responses
=> nil

我已经阅读了大量有关 OpenStruct 现在如何在 2.3 中快 10 倍的文章,但我没有看到会破坏 Collector 和 Response 之间关系的更改。非常感谢任何帮助。 Rails 的版本是 4.2.7.1。

最佳答案

让我们看一下method_missing在当前implementation中的实现:

def method_missing(mid, *args) # :nodoc:
  len = args.length
  if mname = mid[/.*(?==\z)/m]
    if len != 1
      raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
    end
    modifiable?[new_ostruct_member!(mname)] = args[0]
  elsif len == 0
    if @table.key?(mid)
      new_ostruct_member!(mid) unless frozen?
      @table[mid]
    end
  else
    err = NoMethodError.new "undefined method `#{mid}' for #{self}", mid, args
    err.set_backtrace caller(1)
    raise err
  end
end

有趣的部分是中间的代码块,它在方法名称未以 = 结尾且没有附加参数时运行:

if @table.key?(mid)
  new_ostruct_member!(mid) unless frozen?
  @table[mid]
end

如您所见,在实际读取值之前,实现首先检查键是否存在。

这会在未设置键/值时使用返回新 Response.new 的散列来破坏您的实现。因为只是调用 key? 不会触发默认值的设置:

hash = Hash.new { |h,k| h[k] = :bar }
hash.has_key?(:foo)
#=> false
hash
#=> {}
hash[:foo]
#=> :bar
hash
#=> { :foo => :bar }

Ruby 2.2没有这个优化。它只是返回了 @table[mid] 而没有首先检查 @table.key?

关于ruby-on-rails - Ruby 2.3.1 的 OpenStruct 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39278864/

相关文章:

javascript - Ajax 在等待 d3 graphs/.json 响应时加载图形? ( rails )

ruby - 如何将自定义转换添加到 ruby​​ csv?

ruby-on-rails - 如何将递归/嵌套的 OpenStruct 对象转换为哈希

ruby - OpenStruct.new 存储属性但不检索它

java - 通过 RPC 从 Ruby 访问 Java

ruby - 未定义的方法 'each_pair' 与 openstruct

ruby-on-rails - Prawn 设置字体颜色

ruby-on-rails - ActiveRecord::Serializer 中的条件侧载数据(基于 Controller 操作)

ruby-on-rails - Rails构建使用Docker失败。当我使用ruby:alpine image时Nokogiri导致了错误

ruby-on-rails - 如何覆盖 Spree 结帐表单和步骤流程?