使用lib目录中的模块中的类 - Rails 3

时间:2011-08-03 16:41:37

标签: ruby-on-rails

我在lib目录中有一个设置,如下所示:

lib/
  copy_process.rb
  copy_process/
    processor.rb

copy_process.rb和processor.rb包含模块定义CopyProcess。 copy_process.rb也定义了CopyFile类:

module CopyProcess
  class CopyFile
  end
end

processor.rb的结构如下:

module CopyProcess
  class Processer

  end
end

在其中一种方法中,它会创建一个新的副本文件对象:

def append_file_if_valid(file_contents, headers, files, file_name)
  unless headers
    raise "Headers not found"
  else
    files << CopyProcess::CopyFile.new()
  end
end

当我将这些文件用作命令行ruby程序的一部分时,它工作正常。但是,我开始将它放入rails应用程序中,我已经编写了黄瓜/水豚测试来点击按钮等等。我从我的一个AR模型初始化一个Processor对象,并调用上面的方法几次。它似乎找不到CopyFile类,即使我在application.rb中有以下代码

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

有什么想法吗?

=============================================== ================

编辑上面是通过将复制文件类提取到lib下自己的文件中解决的。 我现在有另一个问题:

CopyFile类引用位于lib / copy_process.rb中的模块级辅助方法,如下所示:

module CopyProcess
  # Gets the index of a value inside an array of the given array
  def get_inner_index(value, arr)
    idx = nil
    arr.each_with_index do |e, i|
      if e[0] == value
        idx = i
      end
    end
    return idx
  end

  def includes_inner?(value, arr)
    bool = false
    arr.each { |e| bool = true if e[0] == value  }
    return bool
  end


  # Encloses the string in double quotes, in case it contains a comma
  # @param [String] - the string to enclose
  # @return [String]
  def enclose(string)
    string = string.gsub(/\u2019/, '&rsquo;')
    if string.index(',')
      return "\"#{string}\""
    else
      return string
    end
  end
end

当我进行黄瓜测试时,我收到以下错误:

 undefined method `includes_inner?' for CopyProcess:Module (NoMethodError)
  ./lib/copy_process/copy_file.rb:64:in `set_element_name_and_counter'

这里指的是这个方法:

def set_element_name_and_counter(element_names, name)
  if !CopyProcess::includes_inner?(name, element_names)
    element_names << [name, 1]
  else
    # if it's in the array already, find it and increment the counter
    current_element = element_names[CopyProcess::get_inner_index(name, element_names)]
    element_names[CopyProcess::get_inner_index(name, element_names)] = [current_element[0], current_element[1]+1]
  end
  element_names
end

我还尝试将lib / copy_process /目录中的copy_file.rb和其他文件上移到lib目录中。然后我收到以下错误:

 Expected /Users/aaronmcleod/Documents/work/copy_process/lib/copy_file.rb to define CopyFile (LoadError)
  ./lib/processor.rb:48:in `append_file_if_valid'

错误声明的行创建了CopyFile的实例。我猜rails并不喜欢以这种方式加载文件,对于前一种设置,我认为copy_file.rb在加载模块的其余部分时遇到问题。我试过要求它等等,但没有运气。您还可以在此处找到我最近的代码:https://github.com/agmcleod/Copy-Process/tree/rails

1 个答案:

答案 0 :(得分:4)

首先config.autoload_paths += %W(#{config.root}/lib)就足够了。这告诉rails开始在/ lib中查找结构合理的文件。

其次,我认为你遇到了问题,因为CopyFile不是rails所期望的。据我所知,您的设置“应该”有效,但您是否尝试将CopyFile分隔到copy_process文件夹下的自己的文件中?我的猜测是,由于copy_process文件夹存在,因此期望在那里定义所有CopyProcess::*类而不是copy_process.rb。

编辑:您可以考虑打开另一个问题,但问题的后半部分完全是另一个问题。

您可以在模块中定义方法,

module X
  def method_one
    puts "hi"
  end
end

此表单的方法是模块上的实例方法,它们有非常特殊的限制。例如,您无法从模块定义之外访问它们(我怀疑它们之前是如何工作的)。执行上述内容

> X::method_one
NoMethodError: undefined method `method_one' for X:Module

如果您想从其他范围访问这些方法,您可以选择几种方法。

使用类方法

 module X
   def self.method_one
     puts "hi"
   end
 end
 X::hi #=> "hi"

使用 Mixins

module X
  module Helpers
    def method_one
      puts "hi"
    end
  end
end

class CopyFile
  include X::Helpers

  def some_method
    method_one #=> "hi"
    self.method_one #=> "hi"
  end
end