2016-05-05 2 views
0

これはJavascriptでかなり自明ですが、Rubyでは正解ではありません。Rubyのクラスレベルブロックで「自己」は誰ですか?

class Product 

    after_initialize do |p| 
    p.set_approved 
    end 

    set_approved 
    approved = true 
    end 
end 

私はコードが

def after_initialize(&blk) 
    yield(self) 
end 

のいくつかの並べ替え、両方の方法の状況であると確信しているので、pはなりかなり確信していたので、私は

をしなければならない理由 self、あります
def set_approved(p) 
    p.approved = true 
end 
+1

Rubyでは 'self'はメソッドが定義されているオブジェクトインスタンスまたはクラスコンテキストをほとんど常に指します。' a_i'はどこに存在しますか?それは 'after_initialize'のためのあなたの短い形式ですか?質問でそれをしないようにしてください。 – tadman

+0

@sawa 'self'は(通常)メソッドを呼び出すときにRubyに含めることができます。この場合、承認されたのはdbカラムで、Railsによって自動的に作成されます。 – MCB

+0

私はあなたが 'yield(self)'で持っていたものを逃しました。 – sawa

答えて

3

Rubyでselfは、JavaScriptにはthisがはるかにロックダウンされ、予測可能です。あなたは実際にブロックのバインディングを切り替えるためにあなたの道を離れなければなりません。そして、あなたがそうすると、混乱を招く人々を驚かせることができるので、通常回避されます。

はここで実際に起こって、どのようにあなたがサイドステップすることができ、それは望ましくないですそれならば何だ:それは通常行われていないので、有害な影響を持つことができafter_initializeに与えられたブロックを再バインド

class Product 
    # Usage type #1: Supply a Proc 
    after_initialize do |p| 
    # self here refers to the Product class since this block was defined at the 
    # class level. 
    p.set_approved 
    end 

    # Usage type #2: Call a method 
    after_initialize :trigger_set_approved 

protected 
    def trigger_set_approved 
    # This is an instance method, so self is an instance of Product 
    self.set_approved 
    end 
end 

。そこに定義されているクラスメソッドをProductで呼びたい場合は、class_method_nameの代わりにself.class.class_method_nameに電話する必要があります。

つまり、通常の状況でブロックの実行コンテキストが切り替わらないことが予想されます。

+0

そう、 'after_initialize'はclass_methodなので、なぜ' set_approved 'それが呼び出されたインスタンス' p'を参照してください。そして、どのように彼らはそれが作成されたクラスではなく、ちょうど初期化されたインスタンスの 'self'に' product'を持っていたのでしょうか? – MCB

+0

'set_approved'がインスタンスメソッドとして定義されている場合、' p'引数は必要ありません。 'self'になります。 – tadman

関連する問題