需要与核心Ruby文件同名的Rails lib文件

时间:2014-11-03 10:28:29

标签: ruby-on-rails ruby

在轨道之外,我有以下内容:

|- 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

3 个答案:

答案 0 :(得分:2)

尝试在模块中包装Matrix类,然后refine ... do; enddef方法:

# 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。这是我在问题中提到的解决方法,但我不知道为什么会这样。