簡體   English   中英

將塊傳遞給動態創建的方法

[英]Passing a block to a dynamically created method

我正在創建一個擴展ActiveRecord模型功能的模塊。

這是我的初始設置。

我的課:

class MyClass < ActiveRecord::Base
  is_my_modiable
end

和模塊:

module MyMod
  def self.is_my_modiable
    class_eval do 
      def new_method
        self.mod = true
        self.save!
      end
   end
  end
end
ActiveRecord::Base(extend,MyMod)

我現在要做的是通過傳入一個塊來擴展new_method的功能。 像這樣的東西:

class MyClass < ActiveRecord::Base
  is_my_modiable do
    self.something_special
  end
end

module MyMod
  def self.is_my_modiable
    class_eval do 
      def new_method
        yield if block_given?
        self.mod = true
        self.save!
      end
   end
  end
end

這不起作用,這是有道理的。 在class_eval中,new_method沒有被執行,只是被定義,因此在實際調用該方法之前,yield語句不會被執行。

我試圖將塊分配給class_eval中的類變量,然后在方法中調用該類變量,但是在所有is_my_modiable模型上調用該塊,即使它們沒有將塊傳遞給方法。

我可能會覆蓋該方法以獲得相同的效果,但我希望有一種更優雅的方式。

如果我理解正確,你可以通過將傳遞的塊保存到類對象上的實例變量然后在實例方法中進行評估來解決這個問題。

bl.call不會在這里執行,因為它將在原始上下文(類的)中執行,並且您需要在當前實例的范圍內執行它。

module MyMod
  def is_my_modiable(&block)
    class_eval do
      @stored_block = block # back up block
      def new_method
        bl = self.class.instance_variable_get(:@stored_block) # get from class and execute
        instance_eval(&bl) if bl
        self.mod = true
        self.save!
      end
    end
  end
end

class MyClass
  extend MyMod

  is_my_modiable do
    puts "in my modiable block"
    self.something_special
  end

  def something_special
    puts "in something special"
  end

  attr_accessor :mod
  def save!; end
end

MyClass.new.new_method
# >> in my modiable block
# >> in something special

您可以通過將塊指定為方法參數來執行此操作:

module MyMod
  def self.is_my_modiable
    class_eval do 
      def new_method(&block)
        block.call if block
        self.mod = true
        self.save!
      end
   end
  end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM