我需要将一组通用方法添加到现有模型中。我找到了本教程:
http://chris-schmitz.com/extending-activemodel-via-activesupportconcern/
我认为这是我的目标(我想有一个模块,将其添加到模型中以向其中添加一些方法-一种混合)。
现在,即使我从本教程中进行纯拷贝粘贴,也会因以下错误而感到震惊(没有进一步的解释):
undefined method `key?' for nil:NilClass
Run Code Online (Sandbox Code Playgroud)
这是我的模型的样子:
class Folder < ActiveRecord::Base
attr_accessible :name, :parent_id
has_default
validates :name, presence: true
end
Run Code Online (Sandbox Code Playgroud)
我删除has_default的那一刻,一切恢复正常
再次检查您的代码...
模块结构可能看起来像这样(摘自我的一个肯定有效的项目):
# 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
Run Code Online (Sandbox Code Playgroud)
缺少的是您应该告诉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...
Run Code Online (Sandbox Code Playgroud)
现在应该包含这些模块。
# model.rb
class Model
taggable
end
Run Code Online (Sandbox Code Playgroud)
这是基本插件的工作方式。您问题中提到的教程的作者编写了一个插件,该插件仅适用于从其继承的模型,ActiveRecord::Base因为他正在使用其特定方法(例如update_column)。
如果您的模块不依赖ActiveRecord方法,则无需扩展它(该模块也可以由Mongoid模型使用)。但这绝对不是正确的方法:
class ActiveRecord::Base
include HasDefault
end
Run Code Online (Sandbox Code Playgroud)
如果您确实需要扩展ActiveRecord,请按照以下方式进行操作:
ActiveRecord::Base.extend ModuleName
Run Code Online (Sandbox Code Playgroud)
当然,还有许多其他方法可以根据您的需要编写插件,并以各种方式gems为灵感。
| 归档时间: |
|
| 查看次数: |
2959 次 |
| 最近记录: |