2017-10-11 77 views
0

我有2个项目,把我所造成拉动其他模块,像这样一个大模块“公共代码”项目:红宝石:如何包括外模块Rspec的测试

这里的文件夹结构“我的常见项目”:

  • 我的常见项目
    • 共同
      • file_utils.rb
      • 休息,client.rb
      • 其他Ruby文件与模块...
    • common.rb
    • 的Gemfile
    • 等...

common.rb

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

file_utils.rb

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项目中,我做了一个试验:

  • 我-rspec的项目
    • 规范
      • my_test_spec.rb
      • spec_helper.rb
      • LIB
        • my_class.rb
    • .rspec
    • 的Gemfile
    • 等...

spec_helper.rb

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 

my_class.rb

require "#{File.expand_path('') << '/spec_helper'}" 

class MyClass 

include Common 

    @error_file = open_file('error_file.txt') 
    ... 
end 

我得到的错误:

undefined method `open_file' for MyClass:Class (NoMethodError)

有人能看到什么地方出了错?

+0

'open_file'defined在哪里? – BernardK

+0

@BernardK,open_file是在公共项目中的另一个文件的类中定义的。我会更新这个问题。谢谢 –

回答

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>

+0

我最终使用'扩展通用'来让'open_file'方法起作用,就像你所描述的那样。代码现在可以成功运行。感谢您的帮助。我可能还需要使用'include Common',因为在_my_class.rb_的def方法中使用了模块实例方法。或者我可以将实例方法更改为'def self.my_method'正确吗? –

+0

@AustinL不,如果将实例方法更改为'def self.my_method',它将变成单例(类)方法,并且将不再作为实例方法提供。最好的是'include',然后是'extend'。 – BernardK

+0

听起来不错,我会继续使用'include Common'和'extend Common'。谢谢 –