问题 Rails:基于模块/关注内的父类名动态定义类方法


我想基于包含此Mixin的类名在Mixin中动态生成类方法。

这是我目前的代码:

module MyModule  
  extend ActiveSupport::Concern  

  # def some_methods  
  #   ...  
  # end  

  module ClassMethods  

    # Here is where I'm stuck...
    define_method "#{self.name.downcase}_status" do  
      # do something...  
    end  

  end  
end  

class MyClass < ActiveRecord::Base  
  include MyModule  
end  

# What I'm trying to achieve:
MyClass.myclass_status

但这给了我以下方法名称:

MyClass.mymodule::classmethods_status  

获取方法定义中的基类名称(self,self.name ...),但我无法使其适用于方法名称...

到目前为止,我已经尝试过了

define_method "#{self}"
define_method "#{self.name"
define_method "#{self.class}"
define_method "#{self.class.name}"
define_method "#{self.model_name}"
define_method "#{self.parent.name}"

但这似乎没有做到这一点:/

有什么方法可以检索基类名称(不知道该怎么称为包含我的模块的类)。我一直在努力解决这个问题几个小时,我似乎无法找到一个干净的解决方案:(

谢谢!


9374
2018-02-05 11:47


起源



答案:


你不能这样做 - 在这一点上还不知道哪个类(或类)包含模块。

如果你定义一个 self.included 每次包含模块时都会调用它,并且执行包含的东西将作为参数传递。或者,因为您使用AS :: Concern,您可以这样做

included do 
  #code here is executed in the context of the including class
end

6
2018-02-05 12:26



感谢您的解释。我用了 define_singleton_method 在 - 的里面 included do #... end 块: define_singleton_method "#{self.name}_status" do #... end ` - cl3m


答案:


你不能这样做 - 在这一点上还不知道哪个类(或类)包含模块。

如果你定义一个 self.included 每次包含模块时都会调用它,并且执行包含的东西将作为参数传递。或者,因为您使用AS :: Concern,您可以这样做

included do 
  #code here is executed in the context of the including class
end

6
2018-02-05 12:26



感谢您的解释。我用了 define_singleton_method 在 - 的里面 included do #... end 块: define_singleton_method "#{self.name}_status" do #... end ` - cl3m


我发现了一个干净的解决方案:使用 define_singleton_method (可在ruby v1.9.3中获得)

module MyModule  
  extend ActiveSupport::Concern  

  included do
    define_singleton_method "#{self.name}_status" do
      # do stuff
    end
  end

  # def some_methods  
  #   ...  
  # end  

  module ClassMethods  
    # Not needed anymore!
  end  
end  

6
2018-02-05 14:29





你可以这样做:

module MyModule
  def self.included(base)
    (class << base; self; end).send(:define_method, "#{base.name.downcase}_status") do
      puts "Hey!"
  end

  base.extend(ClassMethods)
end

  module ClassMethods
    def other_method
      puts "Hi!"
    end
  end
end

class MyClass
  include MyModule
end

MyClass.myclass_status
MyClass.other_method

1
2018-02-05 12:28





效劳于 extend

module MyModule  
  def self.extended who
    define_method "#{who.name.downcase}_status" do
      p "Inside"
    end
  end
end  

class MyClass  
  extend MyModule  
end  

MyClass.myclass_status

1
2018-02-05 12:38