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

发布于 2024-11-14 18:16:11 字数 862 浏览 2 评论 0原文

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

我一直无法让这个工作。

例如,我有一个文件: app/modules/acts_as_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)

当我尝试加载调用 actions_as_lockable 的模型时,出现以下错误:

NameError:未定义的局部变量或 方法“acts_as_lockable”

我的猜测是我不应该自动加载模块文件夹,因为当我扩展它时 ActiveRecord 已经被加载了?还有其他方法可以做到这一点吗?我希望能够在开发过程中更改文件而无需重新启动服务器,但这更多的是希望而不是需要。

I have several different acts_as_... custom class methods I'd like to use in my app. I would like the code for those methods to be in files in the app/modules directory.

I have been unable to get this working.

For instance, I have a file: app/modules/acts_as_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

And in application.rb

config.autoload_paths += %W(#{config.root}/app/modules)

When I try to load up a model that calls acts_as_lockable I get the following error:

NameError: undefined local variable or
method `acts_as_lockable'

My guess is that I shouldn't be autoloading the modules folder because ActiveRecord has already been loaded when I extend it? Is there another way to do this? I would like to be able to alter the file during development without restarting my server but that's more of a want that a need.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

想念有你 2024-11-21 18:16:11

我认为你以错误的方式思考这个问题。

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

但只有在您说以下情况时才会加载;

require 'acts_as_lockable'

或者

ActsAsLockable

我建议您永远不想在代码中说出其中任何一个。

您正在寻找的正确范例是“初始化器”。

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

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

或者只包含 require 'acts_as_lockable'

通常我将这样的内容保留在libs 目录

确保 lib 位于加载路径

** config/application.rb **

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

** lib/acts_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

然后位于初始化程序中

**配置/初始化器/acts_as_lockable.rb **

require 'acts_as_lockable'
ActiveRecord::Base.extend ActsAsLockable

I think you're thinking about this in the wrong way.

You are adding this module to the load path,

but it will only load if you either say;

require 'acts_as_lockable'

or

ActsAsLockable

I'd suggest you never really want to say either of these inside your code.

The correct paradigm you're looking for is an "initializer".

I suggest you create a file called "config/initializers/acts_as_lockable.rb"

In this file you can either include the whole code,

or just include a require 'acts_as_lockable'

Normally I keep things like this inside the libs directory

ensure lib is in the load path

** config/application.rb **

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

** lib/acts_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

then in the initializer

** config/initializers/acts_as_lockable.rb **

require 'acts_as_lockable'
ActiveRecord::Base.extend ActsAsLockable
源来凯始玺欢你 2024-11-21 18:16:11

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

ActsAsLockable

class MyModel < ActiveRecord::Base
  acts_as_lockable

  ...
end

我认为acts_as_*模式应该被用作插件和gems来轻松地将功能集成到你的代码中。当您将插件和 gem 集成到项目中时,它们应该处于最终状态,因此您不需要开发模式的重新加载功能。

我希望这有帮助。

The problem is that ruby autoload mechanism is a lazy process: When a constant like ActsAsLockable is used within your code, it looks for a file called acts_as_lockable.rb within the autoload_paths. As You never actually use ActsAsLockable, the file never gets loaded. You could do (although not tremendously beautiful):

ActsAsLockable

class MyModel < ActiveRecord::Base
  acts_as_lockable

  ...
end

I think the acts_as_* pattern is ment to be used be plugins and gems to easily integrate functionality into your code. Plugins and gems are supposed to be in a final state when you integrate them into your project so you would not need the reloading functionality for the development mode.

I hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文