我需要为现有模型添加一组通用方法。我找到了这个教程:
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 的那一刻一切都恢复正常
答案 0 :(得分: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模型使用)。但这肯定是 NOT 正确的方式:
class ActiveRecord::Base
include HasDefault
end
如果你真的需要扩展ActiveRecord,请这样做:
ActiveRecord::Base.extend ModuleName
当然,还有很多其他方法可以根据您的需要编写插件,并采用各种方式gems
作为一个很好的灵感。