2011-01-20 11 views
1

私は「プログラム」と呼ばれるリソースのために、コントローラ上で私の機能テストを実行しようとすると、私のテストの大半はNoMethodErrorの結果に:コントローラで子モデルの関連付けをインスタンス化するにはどうすればいいですか?

NoMethodError: undefined method `programs' for nil:NilClass 

プログラムのリソースは、キャンプのリソースにbelongs_toの関係を持っていますwhich_manyプログラムがあります。この問題を調査した私の経験から、レールコンソール、UI、そしてすべてのモデルテストがうまくいっています。

なぜこの問題が発生していますか、どのように修正できますか?ここで

は、私が使用していたコードです:

キャンプモデル

class Camp < ActiveRecord::Base 

    has_many :contacts 
    has_many :sessions 
    has_many :programs 
    has_many :parents 
    has_and_belongs_to_many :campers 
    has_one :address, :as => :addressable 

    accepts_nested_attributes_for :address, :allow_destroy => true 

    validates :name, :presence => true 
    validates :uri, :presence => true, :uniqueness => true 
    validates :email_address, :email => true, :allow_nil => true 

end 

プログラムモデル

class Program < ActiveRecord::Base 

    belongs_to :camp 

    has_many :program_populations 
    has_many :sessions, :through => :program_populations 
    has_and_belongs_to_many :campers, :join_table => "campers_sessions_programs" 

    accepts_nested_attributes_for :program_populations 

    validates :camp, :presence => true 
    validates :name, :presence => true 
    validates :min_age, :presence => true, :numericality => {:only_integer => true} 
    validates :price, :presence => true, :numericality => true 

end 

プログラムコントローラ

メソッドを作成します。 210
def create 

    @camp = Camp.find_by_uri(params[:camp_id]) 
    @program = @camp.programs.build(params[:program]) #THIS IS THE PROBLEM AREA 

    respond_to do |format| 
    if @program.save 
     format.html { render :text => "program created!", :status => :created } 
     format.xml {render :xml => @program, :status => :created, :location => @program} 
    else 
     format.html { render :action => "new", :status => :bad_request } 
     format.xml { render :xml => @program.errors, :status => :bad_request } 
    end 
    end 
end 

私のテストケース

test "should create program" do 
    assert_difference('Program.count') do 
    post :create, :program => { 
     :camp => camps(:bolo), 
     :name => "Test Program", 
     :min_age => 10, 
     :price => 100.00 
    } 
    end 

    assert_response :created 
    assert_not_nil assigns(:program) 

    get :show, :id => assigns(:program).to_param 
    assert_response :success 
end 

答えて

2

@campnilであるため、このエラーメッセージが表示されます。つまり、実際の障害は前の行にあるCamp.find_by_uri(params[:camp_id])です。簡単に言えば、Railsはキャンプを見つけることができません。

あなたのテストを見ると、実際にはparam[:camp_id]を渡すことはありません。代わりに、あなたはparam[:program][:camp]のパラメータを持っています。これは(私が仮定すると)キャンプオブジェクト全体です。テストを次のように変更してください。

test "should create program" do 
    assert_difference('Program.count') do 
    post :create, 
    {:program => { 
     :name => "Test Program", 
     :min_age => 10, 
     :price => 100.00 
    }, 
    :camp_id => camps(:bolo).id} 
    end 

    assert_response :created 
    assert_not_nil assigns(:program) 

    get :show, :id => assigns(:program).to_param 
    assert_response :success 
end 

これが機能するかどうかを確認してください。

+0

これはうまくいきました!プログラムのオブジェクトの外にcamp_idを移動することは、この問題の解決策です。 – linusthe3rd

0

テストが失敗している理由は、それが@campを見つけることができないということです。 テストも

post :create, :program => { 
    :name => "Test Program", 
    :min_age => 10, 
    :price => 100.00 
}, 
:camp_id => camps(:bolo).id 

にこれを渡して試してみてください、多分あなたは、あなたのコントローラーでCamp.find(params[:camp_id])を呼び出すために意味ですか?

+0

動作しません。彼は 'params [:program]'ハッシュにない 'params [:camp_id]'を使っています。私の答えを見てください。 – vonconrad

+0

ええ、すぐに気づいた(今修正しました)... –

関連する問題