与ActiveSupport ::关注有关的问题

Rus*_*lan 1 ruby-on-rails

我需要将一组通用方法添加到现有模型中。我找到了本教程:

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的那一刻,一切恢复正常

Dav*_*ami 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
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为灵感。