STI 和 RSpec 问题
假设我有这些模型:
class Person < ActiveRecord::Base
end
class Bob < Person
def name
'Bob'
end
end
class John < Person
def name
'John'
end
end
此代码运行良好:
# in controller:
@persons = Person.all
# in view:
- @persons.each do |person|
%p= person.name
但在我的规范文件中,当我编写如下内容时会出现错误:
it "display person names" do
Bob.create!
@person = Person.all.first
print @person.name # Error: undefined method 'name' for #<Person:0x...>
end
但此代码运行良好:
it "display person names" do
Bob.create!
@person = Bob.all.first
print @person.name
end
我做错了什么?
PS 问题仅出现在 RSpec 文件中。控制器中的相同代码运行良好。
更新:找到解决方案!我应该运行“rake db:migrate RAILS_ENV=test”(上次迁移“add_type_to_person”仅应用于开发数据库”)
Assume that I have these models:
class Person < ActiveRecord::Base
end
class Bob < Person
def name
'Bob'
end
end
class John < Person
def name
'John'
end
end
This code works well:
# in controller:
@persons = Person.all
# in view:
- @persons.each do |person|
%p= person.name
But in my spec file I get error when I write something like this:
it "display person names" do
Bob.create!
@person = Person.all.first
print @person.name # Error: undefined method 'name' for #<Person:0x...>
end
But this code works fine:
it "display person names" do
Bob.create!
@person = Bob.all.first
print @person.name
end
What do I do wrong?
P.S. The problem is only in RSpec files. The same code in controllers works well.
UPDATE: the solution is found! I should run "rake db:migrate RAILS_ENV=test" (last migration "add_type_to_person" was applied only to development database")
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在运行测试之前,您可以使用此命令确保测试数据库的架构与开发数据库中的架构相匹配:
如果您使用
rake spec
调用 rspec,则准备工作将会为您进行。You can make sure the schema of your test database matches the schema in your development database using this before running your tests:
If you invoke rspec using
rake spec
, the prepare will happen for you.我们不知道您的架构或数据是什么样的。 (John 和 Bob 是表?)
不过,我不得不猜测 Person 没有 name 属性,这就是第一个测试失败的原因。
因为我不知道你想在这里做什么,所以我无法提供任何进一步的建议 - 但最简单的解决方案是将 name 方法放在 Person 对象上。 (假设它是某种虚拟列,也许您可以从数据中将其抽象出来,这样您就不必在子类中定义它。)
What we don't know is what your schema or data look like. (John and Bob are tables?)
I would have to guess, though, that Person does not have a name attribute, and that is why the first test fails.
Since I don't know what you are trying to do here, I can't advise any further -- but the simplest solution is to put the name method on the Person object. (Assuming that it's a virtual column of some sort, maybe you could abstract it out from the data so that you don't have to define it in the subclasses.)
我猜问题出在你的装置上。我猜你的一个装置在
type
列中没有正确的值,并且偶然,这条记录恰好由Person.all.first
Bob 返回.all
与Person.all
不同 - 第一个将仅返回type = "Bob"
的记录,第二个将返回所有记录记录。通常在测试中使用
.first
不是一个好主意。通常您不知道(不指定)排序顺序,因此返回的记录是随机的。在这种情况下,请检查失败测试返回的记录的
type
字段的值。我想会有一些线索。I guess the problem is in your fixtures. I guess one of your fixtures does not have proper value in
type
column, and by accident, this one record happens to be returned byPerson.all.first
Bob.all
is not the same asPerson.all
- the first will return you only the records for whichtype = "Bob"
, the second will return all records.Usually using
.first
in tests is not a good idea. Usually you do not know (do not specify) the sorting order, so the returned record is random.In this case, check the value of the
type
field of the record returned by the failing test. I guess there will be some clue.