在轨道之外,我有以下内容:
|- file1.rb
|- matrix.rb
具有以下内容:
# in matrix.rb
class Matrix
def foo
puts 'foo'
end
end
# in file1.rb
require_relative 'matrix'
require 'matrix'
Matrix.build(1,1) { 0 }.foo
运行ruby file1.rb
输出:
FOO
我能够包含并调用我的矩阵文件和核心矩阵类。
在Rails中,我有以下目录结构:
|- lib
|-- core_ext
|--- matrix.rb
|- test
|-- lib
|--- core_ext
|---- matrix_test.rb
内容:
# in test/lib/core_ext/matrix_test.rb
require 'test_helper'
require_relative "#{Dir.pwd}/lib/core_ext/matrix.rb"
require 'matrix'
class MatrixTest < ActiveSupport::TestCase
test 'matrix foo' do
Matrix.new.foo
Matrix.build(1,1) { 0 }.foo
assert true
end
end
当我运行rake test test/lib/core_ext/matrix_test.rb
时,我得到NoMethodError: undefined method 'build' for Matrix:Class
,这意味着核心&#39;}&#39;文件尚未加载。
我通过重命名我的lib文件解决了这个问题,但我确实想要包含Ruby的核心Matrix和我的文件而不重命名。有什么建议吗?
p.s:我使用ruby 2.1.4p265和Rails 4.1.6
答案 0 :(得分:2)
尝试在模块中包装Matrix
类,然后refine ... do; end
和def
方法:
# lib/core_ext/my_ext_matrix.rb
module MyExtMatrix
refine Matrix do
def foo
puts 'foo'
end
end
end
现在using
你分机:
# .... some code here ....
class MatrixTest < ActiveSupport::TestCase
using MyExtMatrix
test 'matrix foo' do
Matrix.new.foo
Matrix.build(1,1) { 0 }.foo
assert true
end
end
在using
之后,你应该能够使用核心Matrix
和拥有refine
ed的方法。
答案 1 :(得分:0)
问题在于您首先需要矩阵,而不是核心文件。因此,您的矩阵不会修补补丁,而是定义Matrix
类。在修补它之前明确要求一些东西是一个很好的规则。
尝试将require 'matrix'
添加到您的core_ext/matrix
。
您还可以在没有require 'core_ext/matrix'
的情况下使用_relative
。只需修改搜索路径($ :)即可包含您的lib目录,如果还没有。
答案 2 :(得分:0)
所以我认为这与Rails的自动加载有关,它覆盖了const_missing
并且弄乱了Ruby本身需要文件的方式。 http://urbanautomaton.com/blog/2013/08/27/rails-autoloading-hell/
问题是,无论我在Ruby中的需求顺序如何,我的'矩阵'和核心矩阵都被加载,代码表现得如预期的那样。
当Rails运行并尝试自动加载lib/core_ext/matrix.rb
时,它期望定义CoreExt::Matrix
。当我在代码中执行require 'matrix'
时,这返回false:核心矩阵库未被加载,因为rails假定它已被加载? (我不确定这一点,但这可能发生在这里:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/dependencies.rb)
我要做的是将matrix.rb
重命名为matrix_ext.rb
,即使matrix_ext.rb
中定义的类是Matrix
。这是我在问题中提到的解决方法,但我不知道为什么会这样。