如何从应用程序/模块扩展 ActiveRecord?
我想在我的应用程序中使用几种不同的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为你以错误的方式思考这个问题。
您正在将此模块添加到加载路径中,
但只有在您说以下情况时才会加载;
或者
我建议您永远不想在代码中说出其中任何一个。
您正在寻找的正确范例是“初始化器”。
我建议您创建一个名为“config/initializers/acts_as_lockable.rb”的文件,
在该文件中您可以包含整个代码,
或者只包含
require 'acts_as_lockable'
通常我将这样的内容保留在libs 目录
确保 lib 位于加载路径
** config/application.rb **
** lib/acts_as_lockable.rb **
然后位于初始化程序中
**配置/初始化器/acts_as_lockable.rb **
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;
or
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 **
** lib/acts_as_lockable.rb **
then in the initializer
** config/initializers/acts_as_lockable.rb **
问题是 ruby 自动加载机制是一个懒惰的过程:当在代码中使用像 ActsAsLockable 这样的常量时,它会在 autoload_paths 中查找名为acts_as_lockable.rb 的文件。由于您从未实际使用过 ActsAsLockable,因此该文件永远不会被加载。你可以这样做(虽然不是非常漂亮):
我认为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):
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.