我有一个app/extensions
文件夹,我的自定义异常位于该文件夹中,并且我扩展了一些Ruby / Rails类。目前有两个文件:exceptions.rb
和float.rb
。
该文件夹在ActiveSupport::Dependencies.autoload_paths
:
/Users/mityakoval/rails/efo/app/extensions/**
/Users/mityakoval/rails/efo/app/assets
/Users/mityakoval/rails/efo/app/channels
/Users/mityakoval/rails/efo/app/controllers
/Users/mityakoval/rails/efo/app/controllers/concerns
/Users/mityakoval/rails/efo/app/extensions
/Users/mityakoval/rails/efo/app/helpers
/Users/mityakoval/rails/efo/app/jobs
/Users/mityakoval/rails/efo/app/mailers
/Users/mityakoval/rails/efo/app/models
/Users/mityakoval/rails/efo/app/models/concerns
/Users/mityakoval/rails/efo/app/template.xlsx
/Users/mityakoval/.rvm/gems/ruby-2.4.1@web_app/gems/font-awesome-rails-4.7.0.2/app/assets
/Users/mityakoval/.rvm/gems/ruby-2.4.1@web_app/gems/font-awesome-rails-4.7.0.2/app/helpers
/Users/mityakoval/rails/efo/test/mailers/previews
它在那里列出两次的原因是它应该被自动加载,因为它被放在app
目录下,我还手动将它添加到autoload_paths
中的application.rb
:
config.autoload_paths << File.join(Rails.root, 'app', 'extensions/**')
奇怪的是我的exceptions.rb
已成功加载,但float.rb
除非启用了预先加载,否则spring.rb
不会。
this question的答案说它可能与Spring(我倾向于相信)有关,所以我已将该文件夹添加到%w(
.ruby-version
.rbenv-vars
tmp/restart.txt
tmp/caching-dev.txt
config/application.yml
app/extensions
).each { |path| Spring.watch(path) }
:
/Users/mityakoval/rails/efo/app/extensions/float.rb
我已多次重启Spring和Rails服务器,但没有任何效果。有没有人有任何建议?
Ruby版本:2.4.1 Rails版本:5.1.5
修改
class Float
def comma_sep
self.to_s.gsub('.', ',')
end
end
:
irb> num = 29.1
irb> num.comma_sep
NoMethodError: undefined method `comma_sep' for 29.1:Float
from (irb):2
rails console:
eu-west-1
答案 0 :(得分:1)
monkeypatch核心类的一个更好的方法是创建一个模块并将其包含在要在初始化程序中修补的类中:
# /lib/core_extensions/comma_seperated.rb
module CoreExtensions
module CommaSeperated
def comma_sep
self.to_s.gsub('.', ',')
end
end
end
# /app/initializers/core_extensions.rb
require Rails.root.join('lib', 'core_extensions', 'comma_seperated')
# or to require all files in dir:
Dir.glob(Rails.root.join('lib', 'core_extensions', '*.rb')).each do |f|
require f
end
Float.include CoreExtensions::CommaSeperated
请注意,这里我们根本没有使用Rails自动加载器并明确要求补丁。另请注意,我们将文件放在/lib
而不是/app
。任何非特定于应用程序的文件都应放在/lib
。
将猴子补丁放在模块中可让您通过将代码包含在任意类中来测试代码。
class DummyFloat
include CoreExtensions::CommaSeperated
def initialize(value)
@value = value
end
def to_s
@value.to_s
end
end
RSpec.describe CoreExtensions::CommaSeperated do
subject { DummyFloat.new(1.01) }
it "produces a comma seperated string" do
expect(subject.comma_sep).to eq "1,01"
end
end
这也提供了更好的堆栈跟踪,并且可以更容易地关闭和打开猴子补丁。
但在这种情况下,我认为你一开始并不需要它--Rails有很多帮手可以人性化并定位ActionView::Helpers::NumberHelper中的数字。 NumberHelper也正确地提供了帮助方法,而不是monkeypatching核心Ruby类,这通常是最好的避免。
请参阅: