我想在我的应用中使用几种不同的acts_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)
当我尝试加载调用acts_as_lockable的模型时,我收到以下错误:
NameError:未定义的局部变量或 方法`acts_as_lockable'
我的猜测是我不应该自动加载模块文件夹,因为我扩展它时已经加载了ActiveRecord?还有另一种方法吗?我希望能够在开发期间更改文件而无需重新启动我的服务器,但这更像是一种需要。
答案 0 :(得分:7)
我认为你是以错误的方式思考这个问题。
您正在将此模块添加到加载路径
但只有在你说出来时才会加载;
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
然后在初始化器中
** config / initializers / acts_as_lockable.rb **
require 'acts_as_lockable'
ActiveRecord::Base.extend ActsAsLockable
答案 1 :(得分:0)
问题是ruby自动加载机制是一个惰性进程:当在代码中使用类似ActsAsLockable的常量时,它会在autoload_paths中查找名为acts_as_lockable.rb的文件。由于您从未真正使用ActsAsLockable,因此文件永远不会被加载。你可以做(虽然不是很漂亮):
ActsAsLockable
class MyModel < ActiveRecord::Base
acts_as_lockable
...
end
我认为使用acts_as_ *模式可以使用插件和gem来轻松地将功能集成到代码中。当您将插件和宝石集成到项目中时,它们应该处于最终状态,因此您不需要为开发模式重新加载功能。
我希望这会有所帮助。