【发布时间】:2016-09-17 20:44:41
【问题描述】:
Hello Programmers & Developers!!!,我是 RoR 的初学者,我在 Rails 中创建了一个简单的项目来学习它的工作原理,所以在那个项目中,我在为 create 方法编写规范时遇到了问题的控制器。当我试图在规范文件中传递对象的关联属性时,在控制器中它并没有获得所有属性。
在subjects_controller.rb 文件的create 方法中。
我在这个变量中创建了一个名为attr 的变量,我存储了从subjects_controller_spec.rb 文件发送的所有值。
attr=(params.require(:subject).permit(:name)).merge(:classroom_ids=>params[:subject][:classroom_ids],:school_ids=>params[:subject][:school_ids])
现在,如果我在控制台中使用p attr 打印attr 的值,它的输出就是我想要的确切输出,即
{"name"=>"Computer", "classroom_ids"=>["1", "2"], "school_ids"=>["1"]}
但是,现在我正在做 @subject = Subject.new(attr) 并且打印 @subject 的值会给出以下输出
#<Subject id: nil, name: "Computer", created_at: nil, updated_at: nil>
在运行测试后,我的测试失败了,然后我打印了错误 p @subject.errors 它给了我以下输出
#<ActiveModel::Errors:0x007fc35444a218 @base=#<Subject id: nil, name: "Computer", created_at: nil, updated_at: nil>, @messages={:school_ids=>["is not a number"], :classroom_ids=>["is not a number"]}>
所以,我的实际问题是为什么 subjects_controller.rb 中的 @subject 没有 classroom_ids 和 @987654339 的值@?如果有任何解决方案或建议,请帮助我解决此问题。
下面我为您提供所有必要的详细信息,以了解实际问题.
Ruby 版本 2.2.4
Rails 版本 4.2.0
数据库 MySQL
模型文件subject.rb
class Subject < ActiveRecord::Base
has_and_belongs_to_many :schools
has_and_belongs_to_many :teachers
has_and_belongs_to_many :classrooms
has_and_belongs_to_many :students
validates_presence_of :name, :school_ids, :classroom_ids
validates_numericality_of :school_ids, :classroom_ids
end
控制器文件 subjects_controller_spec.rb
require 'rails_helper'
RSpec.describe SubjectsController, type: :controller do
before(:each) do
@school1 = FactoryGirl.create(:school)
@classroom1 = FactoryGirl.create(:classroom, :school_id=>@school1.id)
@classroom2 = FactoryGirl.create(:classroom, :school_id=>@school1.id)
@subject = FactoryGirl.build(:subject)
@subject.classrooms<<@classroom1
@subject.classrooms<<@classroom2
@subject.schools<<@school1
end
context "POST create" do
it "should be success" do
# p @subject
# p @subject.classrooms
# p @subject.classroom_ids
attributes=@subject.attributes.merge(:classroom_ids=>@subject.classroom_ids,:school_ids=>@subject.school_ids)
# In below line, I'm sending all the values to the controller to create a new subject.
post :create, :subject=>attributes
response.status.should eq 201
end
end
end
控制器文件 subjects_controller.rb
class SubjectsController < ApplicationController
before_action :set_subject, only: [:show, :edit, :update, :destroy]
# GET /subjects
def index
@subjects = Subject.all
end
# GET /subjects/1
def show
end
# GET /subjects/new
def new
@subject = Subject.new
end
# GET /subjects/1/edit
def edit
end
# POST /subjects
def create
attr=(params.require(:subject).permit(:name)).merge(:classroom_ids=>params[:subject][:classroom_ids],:school_ids=>params[:subject][:school_ids])
p attr ### here it prints all the values which I want to create subject.###
@subject = Subject.new(attr)
p @subject ### here is the actual problem, It's not printing all the values that need to create a new subject.###
if @subject.save
redirect_to @subject, notice: 'Subject was successfully created.', status: :created
else
p @subject.errors
render :new, status: :unprocessable_entity
end
end
# PATCH/PUT /subjects/1
def update
if @subject.update(subject_params)
redirect_to @subject, notice: 'Subject was successfully updated.', status: :ok
else
render :edit, :status => :unprocessable_entity
end
end
# DELETE /subjects/1
def destroy
@subject.destroy
redirect_to subjects_url, notice: 'Subject was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_subject
@subject = Subject.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def subject_params
params.require(:subject).permit(:name, :school_ids, :classroom_ids)
end
end
工厂文件subjects.rb
FactoryGirl.define do
factory :subject do
name "Computer"
end
end
RSpec 测试报告
rspec spec/controllers/subjects_controller_spec.rb
{"name"=>"Computer", "classroom_ids"=>["1", "2"], "school_ids"=>["1"]}
#<Subject id: nil, name: "Computer", created_at: nil, updated_at: nil>
#<ActiveModel::Errors:0x007fcdfe8f1a28 @base=#<Subject id: nil, name: "Computer", created_at: nil, updated_at: nil>, @messages={:school_ids=>["is not a number"], :classroom_ids=>["is not a number"]}>
F
Failures:
1) SubjectsController POST create should be success
Failure/Error: response.status.should eq 201
expected: 201
got: 422
(compared using ==)
# ./spec/controllers/subjects_controller_spec.rb:21:in `block (3 levels) in <top (required)>'
Deprecation Warnings:
Using `should` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }` instead. Called from /Users/vishal/project/school_system/spec/controllers/subjects_controller_spec.rb:21:in `block (3 levels) in <top (required)>'.
If you need more of the backtrace for any of these deprecations to
identify where to make the necessary changes, you can configure
`config.raise_errors_for_deprecations!`, and it will turn the
deprecation warnings into errors, giving you the full backtrace.
1 deprecation warning total
Finished in 0.40113 seconds (files took 3.03 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/controllers/subjects_controller_spec.rb:14 # SubjectsController POST create should be success
Coverage report generated for RSpec to /Users/vishal/project/school_system/coverage. 49 / 332 LOC (14.76%) covered.
更多详情可以参考this Github link。
提前感谢您的帮助。
【问题讨论】:
-
@subject.classroom_ids的值是多少? -
@ruby_newbie 当我在 subjects_controller_spec.rb
@subject.classroom_ids中打印时,它给了我[1, 2]。
标签: ruby-on-rails ruby ruby-on-rails-4 web-applications rspec