Подтвердить что ты не робот

Использование factory_girl_rails с Rspec для моделей с именами

У меня есть веб-сервис, который обслуживает рекламу нескольким различным клиентам. Структура объявления зависит от клиентов, и поэтому я использую пространства имен для своих моделей и контроллеров по имени клиента для различения рекламы. С высокого уровня он выглядит так:

'app/models/client1/ad.rb'

class Client1::Ad < ActiveRecord::Base
  attr_accessible :title, :description
end

'app/models/client2/ad.rb'

class Client2::Ad < ActiveRecord::Base
  attr_accessible :title, :description, :source
end

В действительности эти модели более сложны и имеют ассоциации, но это не главное.
Я пишу некоторые модульные тесты, используя rspec-rails 2.4.0 и factory_girl_rails 1.0.1, и все мои заводы работают отлично. Однако я не могу определить фабрики для моделей с именами. Я пробовал что-то вроде:

Factory.define :client1_ad, :class => Client1::Ad do |ad|
  ad.title       "software tester"  
  ad.description "Immediate opening"
end  

и

Factory.define :client2_ad, :class => Client2::Ad do |ad|
  ad.title       "software tester"  
  ad.description "Immediate opening"
  ad.source      "feed"
end

Это не сработало. Я огляделся, но каждый пример, который я видел, использовал модели, не содержащие имен. У кого-нибудь есть идеи? Любые входные данные приветствуются.

4b9b3361

Ответ 1

У меня есть минимальный рабочий пример, возможно, вы можете использовать его, чтобы определить, где ваша проблема. Комментарий, который вы оставили в ответе dmarkow, подсказывает мне, что у вас есть ошибка где-то еще.

приложение/модели/бар/foo.rb

class Bar::Foo < ActiveRecord::Base
end

* дб/мигрировать/20110614204536_foo.rb *

class Foo < ActiveRecord::Migration
  def self.up
    create_table :foos do |t|
      t.string :name
    end
  end

  def self.down
    drop_table :foos
  end
end

спецификации/factories.rb

Factory.define :foo, :class => Bar::Foo do |f|
  f.name 'Foooo'
end

* спецификация/модель/foo_spec.rb *

require 'spec_helper'

describe Bar::Foo do

  it 'does foo' do
    foo = Factory(:foo)
    foo.name.should == 'Foooo'
  end
end

Запуск теста:

$ rake db:migrate
$ rake db:test:prepare
$ rspec  spec/models/foo_spec.rb 
.

Finished in 0.00977 seconds
1 example, 0 failures

Надеюсь, что это поможет.

Ответ 2

Я думаю, возможно, FactoryGirl изменится, так как этот ответ был опубликован. Я сделал, чтобы он работал.

Factory.define do
  factory :foo, :class => Bar::Foo do |f|
    f.name 'Foooo'
  end
end

Ответ 3

С текущей последней версией FactoryGirl (4.5.0) это синтаксис:

FactoryGirl.define do
  factory :client1_ad, class: Client1::Ad do |f|
    f.title       "software tester"
    f.description "Immediate opening"
  end
end

Обратите внимание, что client1_ad может быть любым именем, которое вы хотите, потому что мы уже вынуждены идентифицировать его имя класса.

Ответ 4

Я нашел этот вопрос рассмотрев связанную с FactoryGirl проблему, и после небольшого чтения источника, который я понял, я мог решить свою проблему, переименовав свои заводы.

Когда у меня были классы моделей, которые были помещены во внутренние модули, например: Admin::User, я должен был определять мои фабрики следующим образом:

factory :'admin/user', class: Admin::User do
  #...
end

Вместо

factory :admin_user, class: Admin::User do
  #...
end

Возможно, этот маленький лакомый кусочек информации может кому-то помочь кому-нибудь. Специфика моей проблемы заключалась в том, что я пытался использовать build(described_class) для сборки экземпляров с фабрик в своих спецификациях RSpec, и это отлично работает с классами, не поддерживающими имена, но не с классами внутри модулей. Причина в том, что при поиске фабрик FactoryGirl использует ActiveSupport underscore помощник для нормализации имени factory.

Ответ 5

Вы пробовали передать фактический класс, а не строку с именем класса:

Factory.define :client1_ad, :class => Client1::Ad do |ad|