STI和RSpec问题

时间:2011-07-27 12:08:11

标签: ruby-on-rails ruby ruby-on-rails-3 rspec single-table-inheritance

假设我有这些模型:

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

但在我的spec文件中,当我写这样的东西时,我会收到错误:

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

我做错了什么?

P.S。问题仅出在RSpec文件中。控制器中的相同代码运行良好。

更新:找到解决方案!我应该运行“rake db:migrate RAILS_ENV = test”(最后一次迁移“add_type_to_person”仅应用于开发数据库“)

3 个答案:

答案 0 :(得分:0)

我们不知道您的架构或数据是什么样的。 (约翰和鲍勃是桌子?)

我不得不猜测,Person没有name属性,这就是第一次测试失败的原因。

由于我不知道你在这里要做什么,我不能再进一步建议 - 但最简单的解决方案是将name方法放在Person对象上。 (假设它是某种虚拟列,也许你可以从数据中抽象出来,这样你就不必在子类中定义它了。)

答案 1 :(得分:0)

我猜问题出在你的灯具里。我猜你的其中一个灯具在type列中没有正确的值,而且偶然地,这一条记录恰好由Person.all.first

返回

Bob.allPerson.all不同 - 第一个只返回type = "Bob"的记录,第二个将返回所有记录。

通常在测试中使用.first不是一个好主意。通常您不知道(不指定)排序顺序,因此返回的记录是随机的。

在这种情况下,请检查失败测试返回的记录的type字段的值。我想会有一些线索。

答案 2 :(得分:0)

在运行测试之前,您可以确保测试数据库的模式与开发数据库中的模式匹配:

rake db:test:prepare

如果您使用rake spec调用rspec,则会为您做好准备。