Vis*_*gda 5 ruby rspec web-applications ruby-on-rails ruby-on-rails-4
Hello程序员和开发人员!!!,我是RoR的初学者并在rails中创建一个简单的项目来学习它的工作,所以在那个项目中我面临着编写create控制器方法规范的问题.当我试图在spec文件中传递对象的关联属性时,在控制器中它不会获得所有属性.
在文件的create方法subjects_controller.rb.
我创建了一个attr在这个变量中调用的变量,我存储了从subjects_controller_spec.rb文件发送的所有值.
attr=(params.require(:subject).permit(:name)).merge(:classroom_ids=>params[:subject][:classroom_ids],:school_ids=>params[:subject][:school_ids])
Run Code Online (Sandbox Code Playgroud)
现在,如果我在控制台中打印attrusing 的值,p attr它的输出就是我想要的确切输出,即
{"name"=>"Computer", "classroom_ids"=>["1", "2"], "school_ids"=>["1"]}
Run Code Online (Sandbox Code Playgroud)
但是,现在我正在做@subject = Subject.new(attr)和打印值@subject给出以下输出
#<Subject id: nil, name: "Computer", created_at: nil, updated_at: nil>
Run Code Online (Sandbox Code Playgroud)
并且在运行测试后,我的测试失败,然后我打印出错误,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"]}>
Run Code Online (Sandbox Code Playgroud)
所以,这里是我的实际问题是,为什么@subject在subjects_controller.rb不具有价值classroom_ids和school_ids?如果有任何解决方案或建议,请帮助我解决这个问题.
下面我将为您提供所有必要的细节,以了解实际问题.
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
Run Code Online (Sandbox Code Playgroud)
控制器文件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
Run Code Online (Sandbox Code Playgroud)
控制器文件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
Run Code Online (Sandbox Code Playgroud)
工厂文件subjects.rb
FactoryGirl.define do
factory :subject do
name "Computer"
end
end
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅此Github链接.
在此先感谢您的帮助.
[ "1", "2" ] 不是整数数组而是字符串!@subject 具有classroom_ids 和 school_ids,但参数始终将输入值视为字符串,因此您的Subject 模型中会出现验证错误。所以尝试下面将字符串转换为整数:
params[:subject][:classroom_ids].map(&:to_i)
params[:subject][:school_ids].map(&:to_i)
Run Code Online (Sandbox Code Playgroud)
这个怎么样?
在控制器中没有 map 方法的情况下恢复如下:
params[:subject][:classroom_ids]
params[:subject][:school_ids]
Run Code Online (Sandbox Code Playgroud)
在我的电脑中,通过修改 github 链接中的主题模型如下并通过测试。你能试试这个吗?
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
validate :validate_classroom_ids
validate :validate_school_ids
private
def validate_classroom_ids
if classroom_ids.any?{ |id| !id.is_a?(Integer) }
errors.add(:classroom_ids, 'is not a number')
return false
end
end
def validate_school_ids
if school_ids.any?{ |id| !id.is_a?(Integer) }
errors.add(:school_ids, 'is not a number')
return false
end
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
240 次 |
| 最近记录: |