为什么这个类继承会导致无限递归

时间:2013-05-29 03:12:30

标签: ruby-on-rails ruby ruby-on-rails-3 decorator

我正试图在Rails项目中干掉装饰器。

基本上,我想将任何缺少的方法委托给资源对象(或资源对象的类)。

这是一个简化的例子

# Decorator base class
class Decorator
    attr_accessor :resource

    private

    def method_missing(name, *args, &block)
        self.resource.send(name, *args, &block)
    end

    # infinite recursion happens here
    def self.method_missing(name, *args, &block)
        self.resource.class.send(name, *args, &block)
    end

end

# Decorator class that will be used
class UserCreator < Decorator
    attr_reader :user
    def initialize(params)
        @user = User.new(params[:user])
        self.resource = @user
    end

    def save
        # do special stuff with user object
        if @user.save
            # perhaps do some more stuff after the save
            true
        else
            # perhaps handle the error here
            false
        end
    end

end

# A simple controller example
class SomeController < ApplicationController
    respond_to :json

    def create
        @user = UserCreator.new(params)

        if @user.save
            render :json => @user
        else
            render :json => @user.errors
        end
    end
end

但是,在类Decorator中,在类(单例)方法self.method_missing中发生无限递归。它将resource作为该方法中的name参数传递。

我试图围绕这里发生的事情的控制流程。方法resource通过Decorator存在于基础attr_accessor类中,所以我认为,子类UserCreator也有此方法。所以我不确定为什么它认为resource是一种缺失的方法。如果我摆脱了Decorator超类并且只在method_missing类中实现了UserCreator,那么一切都按预期工作。

非常感谢任何实现此基类以按预期工作的帮助,因此我不必在每个装饰器中实现相同的method_missing方法。

1 个答案:

答案 0 :(得分:2)

第二个method_missing是一个类方法。因此,在此方法中self引用类,而不是实例。

但是,该方法尝试访问self.resource,它是实例的属性,而不是类。

由于Decorator类没有resource属性,因此再次调用method_missing ......再次......再次调用...

  

我试图围绕这里发生的事情的控制流程。   方法资源存在于底层Decorator类中,通过attr_accessor,

它存在于Decorator类的实例中,但不存在于类本身中。

  

所以我想,子类UserCreator也有这种方法。

UserCreator子类的实例拥有它,但不包含子类本身。