Использование классов в модуле из каталога lib - Rails 3 - PullRequest
3 голосов
/ 03 августа 2011

У меня есть настройки в каталоге 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

В одном из своих методов он создает новый файл копииobject:

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, и я написал тесты на огурец / капибару, чтобы нажимать на кнопки и так далее, где это используется.Я инициализирую объект Processor из одной из моих моделей AR и вызываю вышеупомянутый метод несколько раз.Кажется, он не может найти класс CopyFile, хотя у меня есть следующий код в моем приложении. 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

Я также попытался переместить copy_file.rb и другие файлы в каталоге lib / copy_process / вверхуровень в каталоге 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 Ответ

4 голосов
/ 03 августа 2011

Сначала config.autoload_paths += %W(#{config.root}/lib) должно быть достаточно. Это говорит рельсам начать поиск правильно структурированных файлов в /lib.

Во-вторых, я думаю, что вы столкнулись с проблемами, потому что CopyFile не там, где ожидают рельсы. Насколько я знаю, ваша установка «должна» работать, но вы пытались выделить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...