Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby:如果找不到类方法,则在模块中引发错误_Ruby_Module_Include_Metaprogramming - Fatal编程技术网

Ruby:如果找不到类方法,则在模块中引发错误

Ruby:如果找不到类方法,则在模块中引发错误,ruby,module,include,metaprogramming,Ruby,Module,Include,Metaprogramming,我想在模块中放入一些代码,若并没有定义某个方法,就会抛出一个错误。 此模块依赖于此方法的外部定义,因为此方法的实现对于所有类都是不同的。这段代码将帮助开发人员尽早知道他们忘记了实现该方法,而不是在尝试使用模块的功能时 module MyModule def self.included(klass) raise "MyModule: please `def my_method` on #{klass}" unless klass.respond_to?(:my_method) en

我想在模块中放入一些代码,若并没有定义某个方法,就会抛出一个错误。 此模块依赖于此方法的外部定义,因为此方法的实现对于所有类都是不同的。这段代码将帮助开发人员尽早知道他们忘记了实现该方法,而不是在尝试使用模块的功能时

module MyModule
  def self.included(klass)
    raise "MyModule: please `def my_method` on #{klass}" unless klass.respond_to?(:my_method)
  end
end 
如果没有定义方法,我可以很容易地在模块的包含定义中引发错误,但是由于大多数模块都包含在文件的顶部,因此我所需的方法很可能是在类中定义的,但不是在包含模块之前

class MyClass
  include MyModule
  def self.my_method
    # ...
  end
end
这仍然会引发错误:(


只有在类定义中确实没有定义该方法时,才可能引发错误吗?几乎需要一个class.onload回调。如果没有,还有什么其他方法可以减少程序员在没有定义该方法的情况下包含我们的模块的可能性吗?

听起来你想使用
方法ing
定义方法

如果您确实使用了
方法\u missing
,请不要忘记:

  • 调用
    super
    查看未处理的案例
  • 还应实施
    respond\u to?
    方法
看,加和

更新:

听起来像java或C++做静态方法检查,这在Ruby中没有意义:(< /P>) 因为在ruby中:

  • 对象的每个实例都有自己的特征类。给定的对象可能在运行时混合了必要的方法。因此,仅仅因为
    Foo
    在类加载时没有方法是没有意义的
  • RoR hooks method_之类的框架丢失了数据库查询方法所需的方法,并动态创建了这些方法,因此在需要时,该方法可能存在(或不存在)
关于“加载时的类”:实际执行了类定义。请尝试以下操作:

class Foo 
  p "Hi"
end
第一次,也是第一次使用Foo时,你会看到“Hi”,这就是hook-into的神奇之处

class User < ActiveRecord::Base
  # **CALL 'devise' method**
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

  # **CALL attr_accessible method**
  attr_accessible :email, :password, :password_confirmation
end
class用户
因此,也许按照私有约定,开发人员会在所讨论的类的底部添加一个
check\u类
方法调用

我理解其意图,但这似乎是在与ruby的设计工作方式作斗争

作为一个以Java为主的人,我很欣赏这种挫败感。让我猜猜:反复出现的代码被推到生产环境中却缺少方法的情况?:-p

更新2:


wrt
onload
在ruby中,禁止使用冻结的类始终定义新方法(或者实例可以仅为该实例定义新方法)因此,检查一个方法是否不存在只是一个快照检查,而不是静态语言给表带来的确定性检查。这是ruby自己的

用该名称声明一个方法,这只会引发一个错误,以确保用户重新定义该方法如何

module MyModule
  def my_method
    raise "Please implement me"
  end
end


class MyClass 
  include MyModule
  def my_method
    # do something
  end
end

假设您的程序在启动时需要所有文件,并且不使用任何
自动加载
等功能,那么您可以在需要完成所有操作后,但在程序实际启动之前,使用以下功能:

classes_to_check = Object.constants.find_all do |const|
  klass = Object.const_get(c)
  klass.ancestors.include?(MyModule) if klass.kind_of?(Module)
end

classes_to_check.each do |klass|
  raise "MyModule: please `def my_method` on #{klass}" \
    unless klass.respond_to?(:my_method)
end

然而,我个人总是使用Dogbert的解决方案。

我考虑过这一点,尽管在尝试调用该方法之前,您仍然不会感到痛苦。如果您完全忽略该定义,它将几乎具有相同的效果。事实上,它会更好,因为它不会引发一般的非描述
运行时错误
exception,它将引发一个
NoMethodError
异常,它告诉你几乎所有你需要知道的:一个本来应该存在的方法,却没有。这是惯用的Ruby方法,例如
可枚举的
可比较的
方法。我用这种方法来创建“抽象类”。自定义错误消息允许您在上面的评论中说明为什么需要重写该方法。我熟悉特征类,是的,我正在尝试做一些类似于静态方法检查的事情。我的一位同事指出,我们可以将此期望转移到实现MyModule的模型的测试中。我们可以有一个宏acts_as__my_模块,我们可以将它与所有模型测试/规格混合在一起。仍然不会大声抱怨,并且需要额外的程序员投入,但这是最具ruby的eSquence。如果您使用rspec,您可以做类似的事情。从各方面考虑,您可能确实需要一个作为部署的一部分运行并停止deplo的工具我想知道是否有这样的问题。听起来你已经知道了,但我们希望有一个替代方案:-)对于未处理的情况,不要使用
super
。在ruby中使用
super
重写
方法\u missing
时,将尝试转到祖先链中的下一个类或mixin等,并且可能会在那里找到方法名称。相反,请使用
引发NoMethodError
。这是一个更安全的解决方案(来自一位企业级rails开发人员,他刚刚在使用super方面与边缘案例进行了斗争)。