0

モデルユーザーの国ID番号から国名を表示する方法を見つけました。これは、IDでユーザーを見つけた後に名前を表示するためにコントローラーと2つのビューで使用している基本的なコードです。

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

私は Factory Girl を使用して、country_id のデフォルトが米国の 1 であるユーザー レコードをシミュレートしています。このロジックを追加する前は、Rspec2 テストはクリーンでした。テストを実行すると、次のエラーが表示されます。ビューまたはコントローラーに同様のロジックを持つすべてのテストで、エラーが発生します。

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

私が行っている Rspec2 テストの 2 つを次に示します。

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 は User に関係のないインスタンス変数であるため、Rspec2 ファイルで直接何かを行う必要があるのではないかと感じました。

どんな助けでも大歓迎です。今のところそのようなものは見つかりませんでしたが、引き続き探します。

更新 2012 年 6 月 8 日午後 7 時 27 分 CDT

これが私のユーザーコントローラーロジックです。ここに 2 行目を追加すると、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 時 9 分 CDT

これが私の factory.db ファイルです。country_id のユーザーのデフォルト値は 1 です。以下のように定義されたcountry_idで、country_idの宣言なしでこれを試しました。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 factory で country を user.association :country に置き換えました。describe "profile page" do ステートメントの後に、元の 2 つのステートメントを戻します。提案された変更により、エラーはなくなりました。関連付けにより、Country に対応する行が作成されると思います。

すべての助けをありがとう。これを解決したのは、1つの修正で受けた助けの組み合わせでした.

変更された値を確認する方法を理解するために......

更新 2012/06/12 10:55 am

コードをすべて修正すると、 @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 に答える