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

Sch*_*ems 4 ruby module metaprogramming include

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

module MyModule
  def self.included(klass)
    raise "MyModule: please `def my_method` on #{klass}" unless klass.respond_to?(:my_method)
  end
end 
Run Code Online (Sandbox Code Playgroud)

如果没有定义方法,我可以很容易地在模块的包含定义中引发错误,但是由于大多数模块都包含在文件的顶部,所以我的必需方法很可能是在类中定义的,而不是在我的模块包含之前.

class MyClass
  include MyModule
  def self.my_method
    # ...
  end
end
Run Code Online (Sandbox Code Playgroud)

这仍然会引发错误:(

只有在类定义中没有定义方法时才可能引发错误吗?几乎需要一个class.onload回调的排序.如果没有,关于如何减少程序员可能包含我们模块的可能性而没有定义这种所需方法的任何其他想法?

Pat*_*Pat 6

听起来你想要利用method_missingdefine_method.

如果您使用,method_missing请不要忘记:

  • 要求super处理未处理的案件.
  • 还实现了respond_to?一种方法

看看这个问题,加上这个那个.

更新:

听起来我的目标是像Java或c ++那样进行静态方法检查.这在红宝石中真的没有意义:-(

因为在红宝石中:

  • 对象的每个实例都有自己的特征类.给定对象可能在运行时混合了必要的方法.所以只是因为Foo在类加载时没有方法是没有意义的.
  • 像RoR这样的框架会挂钩method_missing并动态创建数据库查询方法所需的方法,因此在需要时可以存在(或不存在)方法.

关于"加载类":真正执行类定义.试试这个:

class Foo 
  p "Hi"
end
Run Code Online (Sandbox Code Playgroud)

您将在第一次使用Foo时看到"Hi".这就是设计方式如何做到他们的魔力.

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
Run Code Online (Sandbox Code Playgroud)

所以也许通过私有约定,开发人员可以check_class在相关类的底部添加一个方法调用?

我理解这个意图,但似乎正在与ruby的设计方式作斗争.

作为一个主要是Java的人,我很欣赏这种挫败感.让我猜一下:重复的代码案例被推到生产中,缺少方法?:-P

UPDATE2:

wrt onload在ruby中禁止使用冻结类获取始终定义的新方法.(或者一个实例可以获得仅为该实例定义的新方法.)因此检查方法的不存在只是一个快照检查,而不是像静态语言带来的那样确定的检查.这是ruby自己的Halting问题


Dog*_*ert 5

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

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


class MyClass 
  include MyModule
  def my_method
    # do something
  end
end
Run Code Online (Sandbox Code Playgroud)