把我的头发扯到这个上:
app/models/concerns/soft_delete.rb:
module SoftDelete
extend ActiveSupport::Concern
module ClassMethods
def testing_a_class
pp "Ima class method"
end
end
def testing_an_instance
pp "Ima instance method"
end
end
class User < ActiveRecord::Base
include SoftDelete
end
app/models/user.rb:
class User < ActiveRecord::Base
testing_a_class
end
现在,在rails控制台中:
x = User.first # I expect "Ima class method" to be printed to the screen
NameError: undefined local variable or method `testing_a_class' for User(no database connection):Class
我不知道你在哪里看到了在定义模块的同一文件中包含模块的想法,但你不能这样做(在rails中),因为rails是如何工作的(自动延迟加载)。
Rails不会在启动时加载所有类。相反,当您引用一个还不存在的类时,rails会尝试猜测它可能位于哪里,并从那里加载它。
x = User.first
在这一行之前,常数User
不存在(假设它以前没有被引用)。当尝试解析此名称时,rails将在每个autoload_paths
中查找文件user.rb
(在谷歌上查找)。它将在app/models/user.rb
找到一个。下次引用User
时,它将只使用这个常量,而不会在文件系统中查找它。
# app/models/user.rb:
class User < ActiveRecord::Base
testing_a_class
end
找到的定义只包含对某个未知方法的调用(因此出现错误)。您的关注文件中的代码未加载,将永远不会加载。要解决此问题,请在模型文件中包含该问题。
# app/models/user.rb:
class User < ActiveRecord::Base
include SoftDelete
testing_a_class
end
现在它应该起作用了。