如何在Rails中扩展类Object?

时间:2011-05-01 07:56:06

标签: ruby-on-rails ruby object

我想将方法​​nil_or_empty?添加到所有类中,因此我定义了

module ObjectExtensions
  def nil_or_empty?
    return self.nil? || (self.respond_to?('empty?') && self.empty?)
  end
end
::Object.class_eval { include ::ObjectExtensions }

它在一个简单的Ruby脚本中运行良好

p nil.nil_or_empty? #=> true
p ''.nil_or_empty? #=> true
p [].nil_or_empty? #=> true
p 0.nil_or_empty? #=> false

但是,当我在Rails 3应用程序中将其添加到我的库文件lib/extensions.rb时,似乎没有添加

NoMethodError (undefined method `nil_or_empty?' for nil:NilClass):
  app/controllers/application_controller.rb:111:in `before_filter_test'

我确实加载了库文件(该文件中的所有其他扩展都正常工作)和

# config/application.rb
# ...
config.autoload_paths << './lib'

我哪里错了?

2 个答案:

答案 0 :(得分:16)

首先,直接重新打开Object类更简洁:

class Object
  def nil_or_empty?
    nil? || respond_to?(:empty?) && empty?
    # or even shorter: nil? || try(:empty?)
  end
end

其次,告诉Rails自动加载/ lib并不意味着当你的应用程序启动时会加载/ lib中的文件 - 这意味着当你使用当前未定义的常量时,Rails将寻找一个文件/ lib对应于该常量。例如,如果您在Rails应用程序代码中引用了ObjectExtensions,并且它尚未在某处定义,则Rails会在lib / object_extensions.rb中找到它。

由于您不能像这样在/ lib中扩展核心类,因此最好将核心扩展放在config / initializers目录中。当您的应用程序启动时,Rails会自动加载其中的所有文件。所以尝试将上面的Object扩展放在config / initializers / object_extension.rb或config / initializers / extensions / object.rb或类似的东西中,一切都应该正常工作。

答案 1 :(得分:7)

在这种特殊情况下,您可以使用Rails提供的Object#blank?。反之,有Object#present?

#blank?与您的方法类似,但也会将"   "等所有空白字符串视为空白。