2016-09-01 7 views
2

Ruby 2.1.5 및 2.2.4에서 새 수집기를 만들면 정확한 결과가 반환됩니다.Ruby 2.3.1에서 OpenStruct 문제

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이 반환됩니다. OpenStruct가 10 배 빠른 2.3 지금 얼마나

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

나는 주위를 읽는 많은 일을했지만 내가 수집 및 응답 사이의 관계를 깰 것이라고 하였다 어떤 변화를 확인할 수 없습니다. 어떤 도움이라도 대단히 감사합니다. Rails 버전은 4.2.7.1입니다.

답변

7

의 현재 implementation에서 method_missing의 구현을 살펴 보자 : 흥미로운 부분은 메소드 이름이 = 때와 끝나지 않았다 때 실행되는 중간에 블록이

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.key?을 먼저 확인하지 않고 방금 @table[mid]을 반환했습니다.

+0

대단히 감사합니다. 나는이 대답의 깊이를 정말로 고맙게 생각한다. – Brit200313