在命名空间模型上使用带有Rspec的factory_girl_rails

时间:2011-06-14 20:02:49

标签: ruby-on-rails-3 namespaces rspec factory-bot

我有一个向多个不同客户提供广告的网络服务。广告的结构因客户端而异,因此,我通过客户名称为我的模型和控制器使用名称空间来区分广告。从高层来看,它看起来像这样:

'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

它没有完成这项工作。我环顾四周,但我看到的每个例子都使用非命名空间的模型。有人有主意吗?任何意见都非常感谢。

5 个答案:

答案 0 :(得分:49)

我这里有一个最小的工作示例,也许你可以用它来查明你的问题所在。你在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

希望它有所帮助。

答案 1 :(得分:12)

我认为自从这个答案发布以来,FactoryGirl可能会发生变化。我做了它的工作

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

答案 2 :(得分:8)

使用当前最新版本的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可以是您想要的任何名称,因为我们已强制识别其 类名

答案 3 :(得分:1)

我发现这个问题正在调查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的{​​{1}}帮助程序来规范化工厂名称。

答案 4 :(得分:0)

您是否尝试传递实际的类,而不是带有类名的字符串:

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