0

我刚刚想出了如何从模型用户上的国家 ID 号显示国家名称。这是我在控制器和两个视图中使用的基本代码,用于在通过 id 找到用户后显示名称:

@country_name = Country.find(@user.country_id).name

我正在使用 Factory Girl 来模拟用户记录,其中 country_id 的默认值为美国的 1。在我添加这个逻辑之前,我的 Rspec2 测试是干净的。现在我在运行测试时收到以下错误。在视图或控制器中具有相似逻辑的每个测试都会产生错误。

ActiveRecord::RecordNotFound:
   Couldn't find Country with id=1

这是我正在做的两个 Rspec2 测试:

describe "profile page" do
  let(:user) { FactoryGirl.create(:user) }
  before { visit user_path(user) }

  it { should have_selector('span',    text: user.first_name+' '+user.last_name) }
  it { should have_selector('title', text: user.first_name+' '+user.last_name) }
end

个人资料页面引用如上所述设置的@country_name。国家名称按预期显示在屏幕上。

我在想我需要以某种方式在 Rspec2 测试中添加一些东西。我不知道在哪里做这个。由于@country_name 是一个与用户无关的实例变量,我觉得也许我需要直接在我的 Rspec2 文件中做一些事情。

任何帮助,将不胜感激。到目前为止我还没有找到这样的东西,但我会继续寻找。

更新 2012 年 6 月 8 日下午 7:27 CDT

这是我的用户控制器逻辑。在此处添加第二行会产生 RSpec2 错误。我在 RSpec2 测试中没有做任何改变。@country_name 在 show.html.erb 中被引用。

def show
  @user = User.find(params[:id])
  @country_name = Country.find(@user.country_id).name
end

我决定试试这个,但得到了同样的错误:

describe "profile page" do
  let(:user) { FactoryGirl.create(:user) }
  let(:country) { FactoryGirl.create(:country) }
  before { visit user_path(user) }

  it { should have_selector('span',    text: user.first_name+' '+user.last_name) }
  it { should have_selector('title', text: user.first_name+' '+user.last_name) }
end

我将以下内容添加到与用户工厂分开的 factory.rb 中。

factory :country do
  id 1
  name "CountryName"
  iso "CN"
end

我的国名应用程序逻辑再次运行良好。

更新 2012 年 6 月 11 日上午 9:09 CDT

这是我的 factory.db 文件。country_id 在 User 中的默认值为 1。我尝试使用如下定义的 country_id 并且没有声明 country_id。我也有没有身份证的乡村工厂。我仍然得到描述的错误。我在这里提交我的问题之前尝试过这个。

FactoryGirl.define do

  factory :user do
    sequence(:first_name)  { |n| "First Name #{n}" }
    sequence(:last_name)  { |n| "Last Name #{n}" }
    sequence(:username)  { |n| "Username#{n}" }
    sequence(:email) { |n| "person_#{n}@example.com" }   
    password "foobar"
    password_confirmation "foobar"
    sequence(:city) { |n| "City #{n}" } 
    sequence(:state_province) { |n| "State/Province #{n}" } 
    active_user "1"
    country_id 1

    factory :admin do
      admin true
      active_user "3"
    end

    factory :blocked do
      active_user "1"
    end

    factory :rejected do
      active_user "2"
    end

    factory :not_visible do
      active_user "3"
      visible false
    end

    factory :visible do
      active_user "3"
      visible true
    end
  end

  factory :country do
    id 1
    name "CountryName"
    iso "CN"
  end

end

更新 2012 年 6 月 11 日下午 5:37 CDT

经过几个小时的继续搜索并完全重新启动我的计算机(叹气),我终于能够让测试正常工作。我在用户工厂用 user.association :country 替换了国家。我把我原来的两个语句放在描述“个人资料页面”做语句后面。通过建议的更改,我现在没有错误。我猜该协会将在 Country 中创建相应的行。

非常感谢所有的帮助。将收到的帮助与解决此问题的一项修改相结合。

弄清楚如何检查更改的值.......

更新 2012 年 6 月 12 日上午 10:55

看起来通过所有代码更正,我可以毫无错误地使用@user.country.name。我将更改我的代码以使用此流线型编码。

4

1 回答 1

2

让我们更多地设置用于测试的变量,如果您使用数据库清理器或类似的东西,这些可能会在每次测试运行时在数据库中被破坏。您应该在 before 块中设置您的工厂:

编辑:我刚刚意识到这可能是因为您试图通过显式输入 id 来匹配记录。这不起作用(数据库会自动设置 ID),但 Factory Girl 应该处理您的关联,看看当您像这样设置 before 块时会发生什么:

before(:each) do
    country = FactoryGirl.create(:country)
    user = FactoryGirl.create(:user, country: country)
    visit user_path(user)
end

我也会删除

id 1

来自您所在国家/地区工厂的线路,以及在用户工厂中将 country_id 设置为 1 的线路。

编辑 2:您需要告诉 Factory Girl 您的关联,不要尝试通过显式设置 id 字段来设置它们,因为这不起作用。

消除

country_id 1

来自用户工厂

id 1

从国家工厂,并将这一行添加到用户工厂:

country

(是的,只是国家本身——只要工厂和协会的名称相同,工厂女孩就足够聪明地弄清楚发生了什么)

顺便说一句,你可以改变这个:

@country_name = Country.find(@user.country_id).name

@country_name = @user.country.name

它在这里无济于事,但它更清洁。

于 2012-06-09T00:49:19.767 回答