开发者

How to go about instantiating child model associations in controllers?

When I try to run my functional tests on a controller for a resource called "Programs", a majority of my tests result in a NoMethodError:

NoMethodError: undefined method `programs' for nil:NilClass

The Program resource has a belongs_to relationship on a Camp resource, which has_many programs. From my experience in researching this issue, everything works fine in the rails console, in the UI, and my model tests all pass.

Why am I getting this issue and how can I go about fixing it?

Here is the code I am using:

The Camp Model

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

The Program Model

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
  v开发者_JAVA百科alidates :name, :presence => true
  validates :min_age, :presence => true, :numericality => {:only_integer => true}
  validates :price, :presence => true, :numericality => true 

end

Programs Controller Create Method

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

My Test Case

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


You're getting this error message because @camp is nil. This means that the actual failure is in the previous line, Camp.find_by_uri(params[:camp_id]). Simply put, Rails can't find the camp.

Looking at your test, you're not actually passing param[:camp_id]. Instead, you have a param[:program][:camp] param, which (I assume) is the entire camp object. Change your test to this instead:

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

And see if that works.


The reason your test is failing is that it can't find a @camp. Try passing this to your test

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

Also, maybe you mean to call Camp.find(params[:camp_id]) in your controller?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜