1

我需要向现有模型添加一组通用方法。我找到了这个教程:

http://chris-schmitz.com/extending-activemodel-via-activesupportconcern/

在我看来,这就是我的目标(我想要一个模块,该模块将被添加到模型中以向其添加一些方法 - 一种混合)。

现在,即使我从教程中进行简单的复制粘贴,我也会遇到以下错误(没有进一步的解释):

undefined method `key?' for nil:NilClass

这是我的模型的样子:

class Folder < ActiveRecord::Base  
  attr_accessible :name, :parent_id  

  has_default

  validates :name, presence: true
end

我删除has_default的那一刻,一切都恢复正常

4

1 回答 1

5

再次检查您的代码...

模块结构可能如下所示(取自我的一个绝对有效的项目):

# lib/taggable.rb

require 'active_support/concern'

module Taggable
  extend ActiveSupport::Concern

  module ClassMethods
    def taggable
      include TaggableMethods # includes the instance methods specified in the TaggableMethods module
      # class methods, validations and other class stuff...
    end
  end

  module TaggableMethods
    # instance methods...
  end
end

缺少的是你应该告诉 Rails 从lib目录加载模块:

# config/application.rb

module AppName
  class Application < Rails::Application
    # Custom directories with classes and modules you want to be autoloadable.
    # config.autoload_paths += %W(#{config.root}/extras)
    config.autoload_paths += %W(#{config.root}/lib)

    # rest ommited...

现在应该包含模块。

# model.rb

class Model
  taggable

end

这就是基本插件的工作方式。您的问题中提到的教程的作者编写了一个插件,该插件仅适用于继承自的模型,ActiveRecord::Base因为他正在使用其特定方法(例如update_column)。

如果您的模块不依赖 ActiveRecord 方法,则无需扩展它(该模块也可能被 Mongoid 模型使用)。但这绝对不是正确的方法:

class ActiveRecord::Base
  include HasDefault
end

如果你真的需要扩展 ActiveRecord,这样做:

ActiveRecord::Base.extend ModuleName

当然,根据您的需要,还有很多其他编写插件的方法,以各种 Railsgems作为一个很好的灵感。

于 2012-10-27T13:42:03.113 回答