我有一个令人困惑的rSpec问题 - 取决于我编写代码的方式,描述'失败'规范的测试失败或描述'成功'规范的测试失败。
以下是创建操作的测试:
describe "POST 'create'" do
describe "failure" do
before(:each) do
@attr = {name: "", type_of_group: ""}
@student_attr = [{name: "Joe", gender: "Male"}, {name: "sally twotrees", gender: "Female"}]
@create = post :create, student_group: @attr, student: @student_attr
end
it "should have the right title" do
@create
response.should have_selector('title', :content => "Create a new group" )
end
it "should render the 'new' page" do
@create
response.should render_template('new')
end
it "should not create a user" do
lambda do
post :create, student_group: @attr
end.should_not change {@user.student_groups.count}
end
it "should flash an error message" do
@create
flash[:error].should =~ /please/i
end
end
describe "success" do
before(:each) do
@attr = FactoryGirl.attributes_for(:student_group)
# @student_attr = {name: "test", gender: "Male"}
end
it "should create a student_group" do
lambda do
post :create, student_group: @attr
end.should change {@user.student_groups.count}.by(1)
end
it "should create students" # do
# lambda do
# post :create, student_group: @attr, student: @student_attr
# end.should change {@student_groups.students.count}.by(1)
# end
it "should flash a success message" do
post :create, student_group: @attr
flash[:success].should =~ /has been added/i
end
it "should redirect" do
post :create, student_group_id: @group, student_group: @attr
response.should be_redirect
end
end
end
所有'失败'测试都因此错误而失败:
Failure/Error: @create = post :create, student_group: @attr, student: @student_attr
ActionView::Template::Error:
`@student_group[students_attributes]' is not allowed as an instance variable name
如果我以这种方式在控制器中编写代码:
def create
@params = params[:student_group][:students_attributes]
@student_group = @user.student_groups.build(params[:student_group])
if @student_group.save
### RE: 'defensive coding' https://stackoverflow.com/questions/14502508/undefined-method-for-nilnilclass-when-pushing-values-to-an-array
if @params.present?
### https://stackoverflow.com/questions/11355820/rails-3-2-iterate-through-an-array
@params.each do |student|
@student_group.students.create(name:"#{student[:name]}", gender: "#{student[:gender]}")
end
end
# new subject path
redirect_to class_path(@student_group), flash: { success: "#{@student_group.name} has been added successfully" }
else
@title = "Create a new group"
flash.now[:error] = "Something's gone wrong. Please try again!"
render 'new'
end
end
如果控制器代码编写如下,则所有'成功'测试都会失败:
def create
@params = params[:student_group][:students_attributes]
@student_group = @user.student_groups.build(params[:student_group])
### http://railsforum.com/viewtopic.php?pid=40056#p40056
if @params.present?
@student = Student.new
else
@student = @student_group.students.build(@params)
end
if @student_group.save
### RE: 'defensive coding' https://stackoverflow.com/questions/14502508/undefined-method-for-nilnilclass-when-pushing-values-to-an-array
if @params.present?
### https://stackoverflow.com/questions/11355820/rails-3-2-iterate-through-an-array
@params.each do |student|
@student_group.students.create(name:"#{student[:name]}", gender: "#{student[:gender]}")
end
end
# new subject path
redirect_to class_path(@student_group), flash: { success: "#{@student_group.name} has been added successfully" }
else
@title = "Create a new group"
flash.now[:error] = "Something's gone wrong. Please try again!"
render 'new'
end
end
答案 0 :(得分:0)
从上面的代码看来你的控制器代码真的搞砸了。在嵌套属性的情况下,你只需要保存父对象。子对象如果有效则会自动保存。此外,您不需要为某些实例对象分配参数。它们应该直接使用。嵌套属性的一个简单示例可以是
User
has_many :comments
accepts_nested_attributes_for :comments
Comment
belongs_to :user
你的控制器代码应该是
def create
@user = User.new(params[:user])
if @user.save
flash[:notice] = 'success'
redirect_to some_path and return
end
render 'new'
end
rspec控制器测试用例可以是
it "should create a user with comments if valid data is provided" do
post :create, "user"=>{"name"=>"Prasad", "comments_attributes"=>{"0"=>{"comment"=>"first comment"}, "1"=>{"comment"=>"second comment"}}, "commit"=>"Save"
user = assigns[:user] #assigns lets u access the instance variable from the controller in the spec
user.should be_valid
user.comments.count.should == 2 #check that all the child models are saved
user.name.should == "Prasad"
user.comments.first.comment.should == 'first comment'
user.comments.last.comment.should == 'second comment'
response.should be_redirect(some_path) #since u redirected in the code
end
严重的是,你需要通过导轨指南。
答案 1 :(得分:0)
我最终使用了这段代码:
def create
@student_group = @user.student_groups.new(params[:student_group])
@params = params[:student_group][:students_attributes]
@student_group = @user.student_groups.build(params[:student_group])
if @student_group.save
### RE: 'defensive coding' http://stackoverflow.com/questions/14502508/undefined-method-for-nilnilclass-when-pushing-values-to-an-array
if @params.present?
### http://stackoverflow.com/questions/11355820/rails-3-2-iterate-through-an-array
@params.each do |student|
@student_group.students.create(name:"#{student[:name]}", gender: "#{student[:gender]}")
end
end
redirect_to new_student_group_subject_path(@student_group), flash: { success: "#{@student_group.name} has been added successfully. Next, add the subjects for this group" }
else
### http://railsforum.com/viewtopic.php?pid=40056#p40056
@student = @student_group.students.build
@title = "Create a new group"
flash.now[:error] = "Something's gone wrong. Please try again!"
render 'new'
end
end