2016-12-20 5 views
1

私はドキュメントからactivesupportの::懸念のthis例で少し混乱しています:あなたが含まれたり、クラスにモジュールを拡張する際にモジュールにclass_evalブロックまたはinstance_evalブロックで定義されたRailsスコープ?

module M 
    def self.included(base) 
    base.extend ClassMethods 
    base.class_eval do 
     scope :disabled, -> { where(disabled: true) } 
    end 
    end 

    module ClassMethods 
    ... 
    end 
end 

self.includedが呼び出されます。 baseは、オブジェクトがクラスオブジェクトでもオブジェクトインスタンスでも、オブジェクトを参照します。 extendbaseには、baseのModule for singleton methodsのメソッドが含まれます。 includeは、メソッドをクラスオブジェクトのインスタンスに追加します。

しかし、class_evalはクラスオブジェクトのインスタンスにインスタンスメソッドを追加するためにも使用されます。ただし、scopeはクラスメソッドです。

オブジェクトを取得およびクエリするためのクラスメソッドを追加します。 scopeので

なぜclass_evalなくinstance_evalを用いた例であり、クラスメソッドでありますか?

+0

class_evalブロックが呼び出されると、クラスメソッドが呼び出されます。この記事は次のように役立ちます:http://engineering.appfolio.com/appfolio-engineering/2013/06/17/ruby-mixins-activesupportconcern – Donato

答えて

1

class_evalは、instance_evalより強力です。

クラスのevalを使用すると、あなたは、あなたがクラスメソッドを定義して呼び出すことができるように、クラスの文脈内のコードを評価するインスタンスメソッド、およびより多くのことができます。

Greeter = Class.new 

Greeter.class_eval do 
    def self.friendly? 
    true 
    end 

    def say_hi 
    "Howdy!" 
    end 
end 

donato = Greeter.new 
donato.say_hi # => "Howdy!" 
Greeter.friendly? # => true 

instance_eval代わりにターゲットを使用してコードを評価インスタンスをレシーバーとして使用するため、インスタンスメソッドを定義しようとすると、少し工夫しなければならないでしょう:

Greeter = Class.new 

Greeter.instance_eval do 
    def friendly? 
    true 
    end 

    define_method(:say_hi) { "Howdy!" } 
end 

donato = Greeter.new 
donato.say_hi # => "Howdy!" 
関連する問題