在命名空间模型上将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
它没有完成任务。我环顾四周,但我看到的每个示例都使用非命名空间模型。有人有什么想法吗?任何意见都将受到高度赞赏。
I have a web service that serves Ads to several different clients. The structure of the Ad varies between clients, and therefore, I am using namespaces for my models and controllers by the client name to differentiate between Ads. From the high level, it looks like this:
'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
In reality, these models are more complex and have associations, but that is not the point.
I am writing some unit tests using rspec-rails 2.4.0 and factory_girl_rails 1.0.1, and all of my factories work great. However, I am not able to define factories for the namespaced models. I've tried something like:
Factory.define :client1_ad, :class => Client1::Ad do |ad|
ad.title "software tester"
ad.description "Immediate opening"
end
and
Factory.define :client2_ad, :class => Client2::Ad do |ad|
ad.title "software tester"
ad.description "Immediate opening"
ad.source "feed"
end
It didn't do the job. I looked around, but every single example that I saw was using non-namespaced models. Anyone have any ideas? Any input is greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我这里有一个最小的工作示例,也许您可以用它来查明您的问题所在。您对 dmarkow 的答案留下的评论向我表明您在其他地方有错误。
app/models/bar/foo.rb
*db/migrate/20110614204536_foo.rb*
spec/factories.rb
*spec/models/foo_spec.rb*
运行测试:
希望有帮助。
I have a minimal working example here, maybe you could use it to pinpoint where your problem is. The comment you left on dmarkow's answer suggests to me that you have an error someplace else.
app/models/bar/foo.rb
*db/migrate/20110614204536_foo.rb*
spec/factories.rb
*spec/models/foo_spec.rb*
Running the test:
Hope it helps.
我想自从这个答案发布后,FactoryGirl 可能会发生变化。我这样做是为了让它发挥作用
I think maybe FactoryGirl changes since this answer was posted. I did to make it work
对于当前最新版本的
FactoryGirl
(4.5.0),语法如下:请注意,
client1_ad
可以是您想要的任何名称,因为我们已经强制识别其类名。With the current latest version of
FactoryGirl
(4.5.0), this is the syntax:Notice that
client1_ad
can be whatever name you want coz we already force identifying its class name.我发现这个问题正在调查与 FactoryGirl 相关的问题,在阅读了一些源代码后,我发现我可以通过重命名我的工厂来解决我的问题。
当我在模块内有命名空间的模型类时,例如:
Admin::User
我应该像这样定义我的工厂:而不是:
也许这一点信息有一天可能会对某人有所帮助。我的问题的具体情况是,我试图使用
build(scribed_class)
从我的RSpec
规范中的工厂构建实例,这对于未命名空间的类来说效果很好,但是不适用于模块内的类。原因是,在内部查找工厂时,FactoryGirl 会使用 ActiveSupport 的下划线助手来规范工厂名称。I found this question looking into a related issue with FactoryGirl and after a little reading of the source I figured out I could solve my problem by renaming my factories.
When I had model classes that were namespaced inside modules, eg:
Admin::User
I should have been defining my factories like this:Rather than:
Maybe this little tidbit of info might help someone someday. The specifics of my issue was that I was trying to use
build(described_class)
to build instances from factories in myRSpec
specs and this works just fine with un-namespaced classes but not with classes inside modules. The reason is that internally when looking up factories FactoryGirl will useActiveSupport
'sunderscore
helper to normalise the factory name.您是否尝试过传递实际的类,而不是带有类名的字符串:
Have you tried passing the actual class, rather than a string with the class name: