0

Rails プロジェクトでデコレータを DRY しようとしています。

基本的に、欠落しているメソッドをリソース オブジェクト (またはリソース オブジェクトのクラス) に委譲したいと考えています。

簡単な例を次に示します

# 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てベースクラスにメソッドが存在するので、サブクラスにもこのメソッドがあると思いました。そのため、メソッドが欠落していると考える理由がわかりません。スーパークラスを取り除き、クラスにs を実装するだけで、すべてが期待どおりに機能します。Decoratorattr_accessorUserCreatorresourceDecoratormethod_missingUserCreator

method_missingこの基本クラスを実装して期待どおりに動作させるための助けがあれば大歓迎です。そのため、すべてのデコレーターで同じメソッドを実装する必要はありません。

4

1 に答える 1

2

2 つ目method_missingは、クラス メソッドです。したがって、このメソッド内selfでは、インスタンスではなくクラスを参照します。

ただし、メソッドself.resourceはクラスではなくインスタンスの属性にアクセスしようとします。

Decoratorクラスにはresource属性がないため、method_missing再度呼び出されます...そしてまた...そしてまた...

ここで何が起こっているかの制御フローに頭を悩ませようとしています。メソッド リソースは、attr_accessor を介して基本 Decorator クラスに存在します。

Decorator クラスのインスタンスには存在しますが、クラス自体には存在しません。

と思ったので、サブクラス UserCreator にもこのメソッドがあります。

UserCreator サブクラスのインスタンスにはそれがありますが、サブクラス自体にはありません。

于 2013-05-29T04:46:17.377 に答える