Ruby`response_to?`在实际为false时返回true

时间:2015-06-22 19:05:52

标签: ruby-on-rails ruby activesupport

我有一个相当简单的空对象类:

class NullObject
  def present?
    false
  end
end

class NullVal < NullObject
  attr_accessor :field

  delegate(
    :allow_edits,
    :box,
    :content,
    :id,
    :locked_for?,
    :number,
    :page_num,
    :page_seq,
    :position_css,
    :position_css_hash,
    :required,
    :required?,
    :size_css,
    :size_css_hash,
    :type,
    to: :field,
  )

  def initialize(field:)
    self.field = field
  end
end

我在rails部分缓存密钥中使用它:

- cache [vals] do
  -# render stuff

我看到以下错误:

NoMethodError - undefined method `cache_key' for #<NullVal:0x000000080ceb78>:
  /home/fletch/.rvm/rubies/ruby-2.1.6/lib/ruby/2.1.0/delegate.rb:343:in `block in delegating_block'
  activesupport (4.2.2) lib/active_support/cache.rb:94:in `retrieve_cache_key'
  activesupport (4.2.2) lib/active_support/cache.rb:95:in `block in retrieve_cache_key'
  activesupport (4.2.2) lib/active_support/cache.rb:95:in `retrieve_cache_key'
  activesupport (4.2.2) lib/active_support/cache.rb:95:in `block in retrieve_cache_key'
  activesupport (4.2.2) lib/active_support/cache.rb:95:in `retrieve_cache_key'
  activesupport (4.2.2) lib/active_support/cache.rb:87:in `expand_cache_key'
  actionpack (4.2.2) lib/action_controller/caching/fragments.rb:22:in `fragment_cache_key'
  actionpack (4.2.2) lib/action_controller/caching/fragments.rb:43:in `read_fragment'
  actionview (4.2.2) lib/action_view/helpers/cache_helper.rb:183:in `read_fragment_for'
  actionview (4.2.2) lib/action_view/helpers/cache_helper.rb:179:in `fragment_for'
  actionview (4.2.2) lib/action_view/helpers/cache_helper.rb:115:in `cache'
  app/views/docs/_doc.html.haml:13:in `block in _app_views_docs__doc_html_haml___3057171325955977412_79957620'

activesupport的相关代码行是:

when key.respond_to?(:cache_key) then key.cache_key

如果我在其中放置puts,则会为true返回key.respond_to?(:cache_key),实际上它是NullVal的实例。如果我在控制台中实例化NullVal,它会返回false。这里发生了什么? method(:respond_to?).source_location为{...}返回nil

1 个答案:

答案 0 :(得分:1)

好的,找出问题所在。我有一个ValDecorator类用于包装NullVal。当我将它打印到控制台时,它显示为#<NullVal:0x0000000a1f3ab0 @field=...>,但它实际上是装饰器。我正在使用DelegateClass

class ValDecorator < DelegateClass(Val)
end

由于Val使用respond_to?并且实际上试图在NullVal上调用它,因此会引发一个令人惊讶的错误。将不得不考虑更多的实施。