Как включить модуль в фабрику factory_girl?

Я пытаюсь повторно использовать вспомогательный метод на всех своих фабриках, однако не могу заставить его работать. Вот моя установка:

Вспомогательный модуль (в spec/support/test_helpers.rb)

module Tests
  module Helpers
    # not guaranteed to be unique, useful for generating passwords
    def random_string(length = 20)
      chars = ['A'..'Z', 'a'..'z', '0'..'9'].map{|r|r.to_a}.flatten
      (0...length).map{ chars[rand(chars.size)] }.join
    end
  end
end

Фабрика (в spec/factories/users.rb)

FactoryGirl.define do
  factory :user do
    sequence(:username) { |n| "username-#{n}" }
    password random_string
    password_confirmation { |u| u.password }
  end
end

Если я запускаю свои тесты (с rake spec), я получаю следующую ошибку везде, где я создаю пользователя с Factory(:user):

 Failure/Error: Factory(:user)
 ArgumentError:
   Not registered: random_string

Что мне нужно сделать, чтобы использовать random_string на своих фабриках?

Я пробовал следующее:

  • используя include Tests::Helpers на каждом уровне моей фабрики (до define, между define и factory :user и внутри factory :user)
  • в spec_helper.rb у меня уже есть следующее: config.include Tests::Helpers и это дает мне доступ к random_string в моих спецификациях
  • просто требуя файл на моей фабрике

Я также безуспешно прочитал следующие ссылки:


person mbillard    schedule 26.10.2011    source источник


Ответы (3)


Как насчет простого:

module Tests
  module Helpers
    # not guaranteed to be unique, useful for generating passwords
    def self.random_string(length = 20)
      chars = ['A'..'Z', 'a'..'z', '0'..'9'].map{|r|r.to_a}.flatten
      (0...length).map{ chars[rand(chars.size)] }.join
    end
  end
end

Потом:

FactoryGirl.define do
  factory :user do
    sequence(:username) { |n| "username-#{n}" }
    password Tests::Helpers.random_string
    password_confirmation { |u| u.password }
  end
end

Хорошо, понял :) Делаем так:

module FactoryGirl
  class DefinitionProxy
    def random_string
     #your code here
    end
  end
end
person apneadiving    schedule 26.10.2011
comment
Это работает так, но я надеялся, что мне не придется писать все пространство имен. Я оставлю вопрос открытым, если кто-то найдет лучший способ. - person mbillard; 26.10.2011
comment
Это работает, хотя я оставил свой вспомогательный модуль как есть (хотя и с методом экземпляра) и включил этот модуль в класс DefinitionProxy. Большое спасибо! - person mbillard; 27.10.2011
comment
Важно отметить: мой метод rand не работал как есть, и мне пришлось заменить его на Kernel.rand из-за конфликта с FactoryGirl. - person mbillard; 27.10.2011

ответ apneadiving у меня не сработал. Мне пришлось сделать следующее:

# /spec/support/factory_helpers.rb
module FactoryHelpers
  def my_helper_method
    # ...
  end
end

FactoryGirl::Proxy.send(:include, FactoryHelpers)

Затем вы можете использовать его следующим образом:

FactoryGirl.define do
  factory :post do
    title { my_helper_method }
  end
end
person cuvius    schedule 25.11.2011
comment
Выглядит намного проще, попробую, когда будет время. - person mbillard; 25.11.2011
comment
FG v4 больше не использует ::Proxy — между прочим, вы получите тот же эффект, заменив FactoryGirl::Proxy.send в ответе @cuvius на FactoryGirl::SyntaxRunner.send. Но обратите внимание, что разработчиком драгоценного камня является обдумывая правильное решение в самой жемчужине, так что следите за развитием событий, если вы этим занимаетесь. - person sameers; 05.12.2013

Я проверил другие ответы вчера (24.04.2012) и... ни один из них не работает.

Похоже, камень Factory Girl (v3.2.0) сильно изменился.

Но я нашел быстрое решение:

# factories.rb
module FactoryMacros
  def self.create_file(path)
    file = File.new(path)
    file.rewind
    return ActionDispatch::Http::UploadedFile.new(:tempfile => file,
                                            :filename => File.basename(file))
  end
end
# also factories.rb
FactoryGirl.define do

  factory :thing do |t|
    t.file { FactoryMacros::create_file("path-to-file")
  end
end
person nothing-special-here    schedule 25.04.2012