Ruby on rails 如何从应用程序/模块扩展ActiveRecord?

Ruby on rails 如何从应用程序/模块扩展ActiveRecord?,ruby-on-rails,ruby,ruby-on-rails-3,metaprogramming,extend,Ruby On Rails,Ruby,Ruby On Rails 3,Metaprogramming,Extend,我有几种不同的表演。。。我想在我的应用程序中使用的自定义类方法。我希望这些方法的代码位于app/modules目录中的文件中 我一直无法让它工作 例如,我有一个文件:app/modules/acts\u as\u lockable module ActsAsLockable def acts_as_lockable before_create :set_lock include InstanceMethods end module I

我有几种不同的表演。。。我想在我的应用程序中使用的自定义类方法。我希望这些方法的代码位于app/modules目录中的文件中

我一直无法让它工作

例如,我有一个文件:app/modules/acts\u as\u lockable

module ActsAsLockable

    def acts_as_lockable
        before_create :set_lock

        include InstanceMethods
    end

    module InstanceMethods
        protected

        def set_lock
            now = Time.now.to_s
            self.lock = Digest::SHA1.hexdigest(now)
        end
    end

end

ActiveRecord::Base.extend ActsAsLockable
和在application.rb中

config.autoload_paths += %W(#{config.root}/app/modules)
当我尝试加载一个调用acts_as_lockable的模型时,我得到以下错误:

NameError:未定义的局部变量或 方法“作为可锁定的”


我猜我不应该自动加载modules文件夹,因为当我扩展它时,ActiveRecord已经被加载了?还有别的办法吗?我希望能够在开发过程中更改文件,而无需重新启动服务器,但这更像是一种需要。

问题是ruby自动加载机制是一个惰性的过程:当代码中使用ActsAsLockable之类的常量时,它会在自动加载路径中查找名为acts_as_lockable.rb的文件。由于您从未实际使用ActsAsLockable,因此永远不会加载该文件。你可以做(虽然不是非常漂亮):

可执行锁定
类MyModel
我认为acts_as_*模式可以作为插件和gem使用,以方便地将功能集成到代码中。插件和gem应该在您将它们集成到项目中时处于最终状态,这样您就不需要为开发模式重新加载功能


我希望这能有所帮助。

我认为你的想法是错误的

您正在将此模块添加到加载路径

但只有当你说:

require 'acts_as_lockable'

我建议你永远不要在你的代码里说这两个词

您正在寻找的正确范例是“初始值设定项”

我建议您创建一个名为“config/initializers/acts_as_lockable.rb”的文件

在这个文件中,您可以包含整个代码

或者只包含一个
require'acts\u as\u lockable'

通常我会将类似的内容保存在libs目录中

确保lib位于加载路径中

**config/application.rb**

config.autoload_paths += %W(#{config.root}/lib)
**lib/act_as_lockable.rb**

module ActsAsLockable

  def acts_as_lockable
    before_create :set_lock

    include InstanceMethods
  end

  module InstanceMethods
    protected

    def set_lock
      now = Time.now.to_s
      self.lock = Digest::SHA1.hexdigest(now)
    end
  end

end
require 'acts_as_lockable'
ActiveRecord::Base.extend ActsAsLockable
然后在初始值设定项中

**config/initializers/act_as_lockable.rb**

module ActsAsLockable

  def acts_as_lockable
    before_create :set_lock

    include InstanceMethods
  end

  module InstanceMethods
    protected

    def set_lock
      now = Time.now.to_s
      self.lock = Digest::SHA1.hexdigest(now)
    end
  end

end
require 'acts_as_lockable'
ActiveRecord::Base.extend ActsAsLockable

谢谢你,你的工作很有魅力。我意识到这可能不是最实际的解决方案,但出于某种原因,我讨厌在我的模型中看到include语句。