如何将文件名规范化为没有路径的mp3文件名?红宝石

时间:2017-10-04 22:39:24

标签: ruby tdd

我正在尝试解决实验室,但我不确定发生了什么。我要做的是我必须从目录导入一些文件名(.mp3' s)然后使用文件名来制作一些对象。我仍然坚持从目录中获取文件名。测试要求我

"将文件名规范化为仅没有路径的mp3文件名"

测试如下:

  it 'normalizes the filename to just the mp3 filename with no path' do
  test_music_path = "./spec/fixtures/mp3s"
  music_importer = MP3Importer.new(test_music_path)

  expect(music_importer.files).to include("Action Bronson - Larry Csonka - indie.mp3")
  expect(music_importer.files).to include("Real Estate - Green Aisles - country.mp3")
  expect(music_importer.files).to include("Real Estate - It's Real - hip-hop.mp3")
  expect(music_importer.files).to include("Thundercat - For Love I Come - dance.mp3")
end

我的代码是:

class MP3Importer
 attr_accessor :path

 def initialize(path)
  @path = path
 end

 def files
  Dir.chdir(@path)
  filename = Dir.glob("*.mp3")
  filename
 end
end

这也是通过这两个测试:

  describe '#initialize' do
it 'accepts a file path to parse mp3 files from' do
  test_music_path = "./spec/fixtures/mp3s"
  music_importer = MP3Importer.new(test_music_path)

  expect(music_importer.path).to eq(test_music_path)
end

describe '#files' do
it 'loads all the mp3 files in the path directory' do
  test_music_path = "./spec/fixtures/mp3s"
  music_importer = MP3Importer.new(test_music_path)

  expect(music_importer.files.size).to eq(4)
end

但它产生的错误是:

Failure/Error: expect(music_importer.files).to include("Action Brons
 Errno::ENOENT:
   No such file or directory @ dir_chdir - ./spec/fixtures/mp3s

老实说我不知道​​将文件名规范化为mp3文件名没有路径意味着什么?这是非常误导的。我的#files方法中已经有变量filename的文件名数组。

我的问题是:

  1. 语句是什么"将文件名规范化为仅没有路径的mp3文件名"意思 ?考试要我做什么?
  2. 发布的代码中发生了什么?
  3. 为什么错误指向目录?当目录确实有所需的文件?

1 个答案:

答案 0 :(得分:1)

初步说明:发布所有代码并且只发布最少的代码,以便我们可以复制粘贴并执行它来重现错误。在这种情况下,RSpec标签和RSpec的版本也很有用。

当我执行你的代码时:

   No such file or directory @ dir_chdir - ./spec/fixtures/mp3s
 # ./lib/t_a.rb:14:in `chdir'

错误发生在第14行的声明中:

Dir.chdir(@path)

这给出了chdir在当前工作目录中找不到所请求的子目录的线索。为什么?添加跟踪以显示当前工作目录:

def files
    puts "in files, path=#{@path}"
    puts "wd=...#{Dir.getwd.sub(/.*ruby(.*)/, '\1')}"
    current_dir = Dir.getwd
    Dir.chdir(@path)
...

并运行测试(我在...devl/ruby/zintlist/mp3_importer工作):

$ rspec

MP3Importer
  #initialize
    accepts a file path to parse mp3 files from
  #files
in files, path=./spec/fixtures/mp3s
wd=.../zintlist/mp3_importer
    loads all the mp3 files in the path directory
  #xxxx
in files, path=./spec/fixtures/mp3s
wd=.../zintlist/mp3_importer/spec/fixtures/mp3s

你看到了不同之处:

wd=.../zintlist/mp3_importer
wd=.../zintlist/mp3_importer/spec/fixtures/mp3s

执行files时,会产生副作用:当前目录已更改。在files的第二次执行中,Dir.chdir开始在第一次执行所留下的当前目录中搜索,即.../mp3_importer/spec/fixtures/mp3s,而mp3s当然不包含{{1}因此错误./spec/fixtures/mp3s

解决方案是恢复输入方法时当前的目录:

No such file or directory

然后跟踪显示它已经恢复:

def files
    puts "in files, path=#{@path}"
    puts "wd=...#{Dir.getwd.sub(/.*ruby(.*)/, '\1')}"
    current_dir = Dir.getwd
    Dir.chdir(@path)
    filenames = Dir.glob("*.mp3")
    Dir.chdir(current_dir)
    filenames
end

您可能已经知道,如果您在wd=.../zintlist/mp3_importer ... wd=.../zintlist/mp3_importer 块内处理文件,则在块退出时文件将关闭。这同样适用于恢复当前目录。来自The Pickaxe Dir.chdir:

  

如果给出了一个块,则传递新当前的名称   目录,并以此作为当前执行块   目录。块时恢复原始工作目录   退出。

鉴于这些文件:

File.open ... do ... end

#file t.rb

class MP3Importer
    attr_accessor :path

    def initialize(path)
        @path = path
    end

    def files
#        puts "in files, path=#{@path}"
#        puts "wd=#{Dir.getwd.sub(/.*ruby(.*)/, '\1')}"
        filenames = Dir.chdir(@path) do | path |
#            puts path
            Dir.glob("*.mp3")
        end
        puts "names=#{filenames}"
        filenames
    end
end

执行:

# file t_spec.rb

require 't'

RSpec.describe MP3Importer do
    let(:test_music_path) { "./spec/fixtures/mp3s" }
    let(:music_importer)  { MP3Importer.new(test_music_path) }

    describe '#initialize' do
        it 'accepts a file path to parse mp3 files from' do
            expect(music_importer.path).to eq(test_music_path)
        end
    end

    describe '#files' do
        it 'loads all the mp3 files in the path directory' do
            expect(music_importer.files.size).to eq(4)
        end
    end

    describe '#xxxx' do
        it 'normalizes the filename to just the mp3 filename with no path' do
            expect(music_importer.files).to include('f4.mp3')
        end
    end
end

所有测试均为绿色。

由于方法返回值是上次执行的表达式的值,您可以像这样简化$ ruby -v ruby 2.4.0rc1 (2016-12-12 trunk 57064) [x86_64-darwin15] $ rspec -v RSpec 3.6.0.beta2 - rspec-core 3.6.0.beta2 - rspec-expectations 3.6.0.beta2 - rspec-mocks 3.6.0.beta2 - rspec-support 3.6.0.beta2 $ rspec MP3Importer #initialize accepts a file path to parse mp3 files from #files names=["f1.mp3", "f2.mp3", "f3.mp3", "f4.mp3"] loads all the mp3 files in the path directory #xxxx names=["f1.mp3", "f2.mp3", "f3.mp3", "f4.mp3"] normalizes the filename to just the mp3 filename with no path Finished in 0.00315 seconds (files took 0.09868 seconds to load) 3 examples, 0 failures

files
  

声明"标准化......是什么意思?

我不知道。我想它只收集名称与某个模式相对应的文件,def files Dir.chdir(@path) do | path | Dir.glob("*.mp3") end end

我可以说RDoc从命令行获取输入文件名,并将它们传递给名为*.mp3的例程:

normalized_file_list