ruby-on-rails Rails:未找到同一模块中的类

t40tm48m  于 2022-12-24  发布在  Ruby
关注(0)|答案(3)|浏览(197)

我有一个问题。我是Ruby的新手,所以我正在为一些问题而挣扎,这些问题我可以在几个小时后解决,但这个问题现在困扰了我一天。
我在/lib/math/calc.rb中创建了一个包含以下内容的类:

module Math
    module Calc
        class << self
            def check!(value1: nil, value2: nil)
                raise Error.new(message: "value1 is required") unless value1
                raise Error.new(message: "value2 is required") unless value2
                Divide.send!(value1: :value1, value2: :value2)
            end
        end
    end
end

然后我还有一个类Divide,它位于:/lib/math/calc/divide.rb,其含量为:

module Math
    module Calc
        class Divide
            class << self
                def send!(value1: nill, value2: nill)
                    # More code here
                end
            end
        end
    end
end

现在当我打电话:Math::Calc.check!(5, 5),我得到以下错误:

NameError: uninitialized constant Math::Calc::Divide

我已经尝试插入require 'divide',但那些导入不存在,他说。
我到底做错了什么?

4nkexdtk

4nkexdtk1#

在Rails中,autoloader具有以下根目录:

  • /app的任何子目录。
  • /app/controllers/concerns
  • /app/models/concerns

根目录(又名自动加载路径)是自动加载程序将查找根级常量的目录。
因此,您可以通过将代码移动到现有根目录中来“修复”问题。
但是由于常量Math已经是Ruby核心的一部分,引用可能实际上不会导致自动加载器加载常量。这可能会给经典的自动加载器带来问题,但不会给Zeitwerk带来问题,Zeitwerk有常量的Map。如果你想用一个非常有问题的添加来monkeypatch一个核心类,你应该认真考虑这里(不要这样做)。一般来说,如果它不是你的名字空间,让你的肮脏的小nubbies远离。
/lib是故意不自动加载的。我们假设您在需要时会显式地要求代码在那里。如果您想将/lib添加到eager和autoloading路径中,您可以这样做。

module MyApplication
  class Application < Rails::Application
    # I don't actually recommend this.
    config.autoload_paths << Rails.root.join('lib')
    config.eager_load_paths << Rails.root.join('lib')
  end
end

然后真的有一个问题,这段代码只是奇怪和错误,只是不是Ruby。
如果要使关键字参数成为必需参数,请将其设置为必需参数:

module Calc
  def self.check!(value1:, value2:)
    Divide.send!(...)
  end
end

但是不清楚为什么你甚至想在另一端使用关键字参数。在函数式函数中除法的元数总是2(divide(x, y)),而在面向对象的方法中是1(x.divide(y))。虽然使用关键字通常比使用大量的位置参数要好--如果你给它们起一个没有意义的名字,你会使代码变得不必要的冗长,并且更难实际使用。
但最终这段代码是非常非rubyeske的,因为在Ruby中,通过向对象发送消息:/, number来执行诸如除法之类的操作。

10/2

这将调用Integer上的方法/
如果你想探索如何实际编写一个计算器,我会写这样的东西:
一个三个三个一个

c9qzyr3d

c9qzyr3d2#

如果你想用普通的Ruby来做,你只需要在你的模块中有Divide文件,这样解释者就知道文件的位置了
文件树:

  • 库/数学/计算rb
  • 库/数学/计算/除法. rb
# lib/math/calc.rb
require_relative 'calc/divide'

module Math
  module Calc
    class << self
      def check!(value1: nil, value2: nil)
        raise Error.new(message: "value1 is required") unless value1
        raise Error.new(message: "value2 is required") unless value2
        Divide.send!(value1: :value1, value2: :value2)
      end
    end
  end
end

除此之外:注意,这里没有定义Error类,也没有向Divide.send!发送正确的值。要做到这一点,应该发送Divide.send!(value1: value1, value2: value2)

cedebl8k

cedebl8k3#

也许试试下面的。
库/数学/计算rb

module Math
  module Calc
    require_relative './calc/divide'
    extend self

    def check!(value1: nil, value2: nil)
      raise Error.new(message: "value1 is required") unless value1
      raise Error.new(message: "value2 is required") unless value2
      Divide.send!(value1: :value1, value2: :value2)
    end
  end
end

库/数学/计算/除法. rb

module Math
  module Calc
    class Divide
      def self.send!(value1: nill, value2: nill)
        # More code here
      end
    end
  end
end

此外,还可以在应用程序中创建lib目录,例如app/lib

相关问题