我有2个项目,一个“公共代码”项目,我已经把它变成了一个大模块,可以引入其他模块:
以下是“my-common-project”的文件夹结构:
require 'bundler'
Bundler.require
require_relative './common/file-utils.rb'
require_relative './common/rest_client.rb'
...
module Common
include FileUtils
include RestClient
# include other modules here...
module Common
module FileUtils
def open_file(file_name)
dir = File.expand_path('') << '/lib'
FileUtils.mkdir_p(dir) unless File.directory?(dir)
File.open(File.expand_path('') << "/lib/#{file_name}", 'w')
end
end
end
我还有一个Rspec项目,我正在做一个测试:
require 'bundler'
require 'csv'
require_relative './lib/fp_relationship_api'
require_relative './../../../../../RubyProjects/mksta-common/common'
Bundler.require
RSpec.configure do |config|
...
config.include Common
...
end
require "#{File.expand_path('') << '/spec_helper'}"
class MyClass
include Common
@error_file = open_file('error_file.txt')
...
end
我收到错误:
MyClass的未定义方法`open_file':Class(NoMethodError)
有人能看出出了什么问题吗?
答案 0 :(得分:1)
我应该立即看到问题,但没有。你看到了:
之间的区别lib/my_class.rb:9:in `<class:MyClass>': undefined method `open_file' for MyClass:Class (NoMethodError)
当open_file
出现在MyClass的正文中时,并且:
lib/my_class.rb:16:in `m': undefined method `open_file' for #<MyClass:0x007fbb0d10cc30> (NoMethodError)
如果我把它放在def
:
def m
@error_file = open_file('error_file.txt')
在第一种情况下,您位于MyClass
的正文中,其中open_file
未定义。在第二种情况下,我删除了include Common
。
为了进行研究,我已经定义了重现错误所需的最低限度。
文件.../lib/file_utils.rb
,与您的相同。
档案.../lib/common.rb
:
require_relative 'file_utils'
module Common
puts "Common instance methods before include : #{instance_methods(true).sort}"
include FileUtils
puts "Common instance methods after include : #{instance_methods(true).sort}"
puts "Common class methods before extend : #{singleton_methods(true).sort}"
extend FileUtils
puts "Common class methods after extend : #{singleton_methods(true).sort}"
end
档案.../lib/my_class.rb
:
require_relative 'common'
class MyClass
# puts "MyClass methods before include : #{instance_methods(true).sort}"
include Common
# puts "MyClass methods after include : #{instance_methods(true).sort}"
puts "self=#{self}"
puts "MyClass class methods before extend : #{singleton_methods(true).sort}"
extend Common
puts "MyClass class methods after extend : #{singleton_methods(true).sort}"
@error_file = open_file('error_file.txt')
puts "in MyClass error_file=#{@error_file}"
def m
@error_file = open_file('error_file.txt')
puts "in m error_file=#{@error_file}"
end
end
MyClass.new.m
执行:
$ ruby -w lib/my_class.rb
Common instance methods before include : []
Common instance methods after include : [:open_file]
Common class methods before extend : []
Common class methods after extend : [:open_file]
self=MyClass
MyClass class methods before extend : []
MyClass class methods after extend : [:open_file]
in MyClass error_file=#<File:0x007ff2621fcdc0>
in m error_file=#<File:0x007ff2621fc938>
<强>解释强>
由于您使用@error_file = open_file('error_file.txt')
的方式,您位于MyClass
的主体中,仅在解释器读取类定义时执行。open_file
。如果在没有接收器的情况下使用self
之类的方法,则会将其发送到隐式接收器MyClass
,即open_file
。但是在定义时,def self.open_file(file_name)
不是类方法,而是实例方法。
如果需要类方法(更确切地说是单例方法),则必须将其定义为
extend <module>
或使用"dynamic_templates": [
{
"message_field": {
"match": "message",
"match_mapping_type": "string",
"mapping": {
"fielddata": {
"format": "disabled" // PROBLEM HERE!
},
"index": "analyzed",
"omit_norms": true,
"type": "string"
}
}
},
。