2017-10-11 70 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'。謝謝 –