我有一个网络应用程序,其中我在两个表之间有以下关系:一个主题和类别表,其中一个类别有很多主题,一个主题属于一个类别。
class Topic < ActiveRecord::Base
has_many :comments, dependent: :destroy
belongs_to :category
belongs_to :user
validates :subject, :body, :user_id, :category_id, presence: true
private
def self.find_by_id(params)
if params[:topic_id]
find(params[:topic_id])
else
find(params[:id])
end
end
def self.build_topic_comment(params, comment_params)
@topic = Topic.find_by_id(params)
@topic.comments.build(comment_params)
end
def self.load_comments(topic)
topic.comments.build
end
end
class Category < ActiveRecord::Base
has_many :topics, dependent: :destroy
belongs_to :user
validates :name, :user_id, presence: true
private
def self.find_by_id(params)
if params[:category_id]
find(params[:category_id])
else
find(params[:id])
end
end
def self.load_topics_desc(category)
category.topics.order(created_at: :desc)
end
def self.build_category_topic(params, topic_params)
@category = Category.find_by_id(params)
@category.topics.build(topic_params)
end
end
我添加了通过更新主题的外键(称为类别ID)将主题移动到其他类别的功能。这是通过我自己编写的管理面板完成的,它工作正常。当我检查主题索引页面时,他的类别列确实已更新。
问题是我创建的rspec测试失败并给出以下错误:
Admin::TopicsController with administrator access PATCH #update with valid attributes updates a topic
Failure/Error: if @topic.update(topic_params)
ActiveRecord::InvalidForeignKey:
PG::ForeignKeyViolation: ERROR: insert or update on table "topics" violates foreign key constraint "fk_rails_d5d593e6f0"
DETAIL: Key (category_id)=(3) is not present in table "categories".
: UPDATE "topics" SET "subject" = $1, "body" = $2, "category_id" = $3, "updated_at" = $4 WHERE "topics"."id" = $5
# ./app/controllers/admin/topics_controller.rb:19:in `update'
# /Users/Beno/.rvm/gems/ruby-2.2.2/gems/devise-4.1.1/lib/devise/test_helpers.rb:19:in `block in process'
# /Users/Beno/.rvm/gems/ruby-2.2.2/gems/devise-4.1.1/lib/devise/test_helpers.rb:75:in `catch'
# /Users/Beno/.rvm/gems/ruby-2.2.2/gems/devise-4.1.1/lib/devise/test_helpers.rb:75:in `_catch_warden'
# /Users/Beno/.rvm/gems/ruby-2.2.2/gems/devise-4.1.1/lib/devise/test_helpers.rb:19:in `process'
# ./spec/controllers/admin/topics_controller_spec.rb:79:in `block (5 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# PG::ForeignKeyViolation:
# ERROR: insert or update on table "topics" violates foreign key constraint "fk_rails_d5d593e6f0"
# DETAIL: Key (category_id)=(3) is not present in table "categories".
# ./app/controllers/admin/topics_controller.rb:19:in `update'
rspec测试文件:
require 'rails_helper'
RSpec.describe Admin::TopicsController, type: :controller do
describe 'with administrator access' do
let(:valid_attributes) { attributes_for(:topic) }
let(:invalid_attributes) { attributes_for(:topic, category_id: nil) }
let(:updated_attributes) { attributes_for(:topic, category_id: 3) }
before(:each) do
@topic = create(:topic)
admin = create(:admin)
sign_in admin
end
describe 'GET #index' do
it 'renders the index template' do
get :index
expect(response).to render_template(:index)
end
it 'loads all the topics in the database' do
get :index
expect(assigns(:topics)).to eq([@topic])
end
end
describe 'GET #show' do
it 'renders the show template' do
get :show, id: @topic
expect(response).to render_template(:show)
end
it 'retrieves a topic from the database' do
get :show, id: @topic
expect(assigns(:topic)).to eq(@topic)
end
it 'loads the topics comments' do
topic = create(:topic_with_comments)
get :show, id: topic
expect(topic.comments.length).to eq(5)
end
end
describe 'GET #edit' do
it 'renders the edit template' do
get :edit, id: @topic
expect(response).to render_template(:edit)
end
it 'retrieves a topic from the database' do
get :edit, id: @topic
expect(assigns(:topic)).to eq(@topic)
end
end
describe 'PATCH #update' do
context 'with valid attributes' do
it 'finds a topic in the database' do
get :edit, id: @topic
expect(assigns(:topic)).to eq(@topic)
end
it 'updates a topic' do
patch :update, id: @topic, topic: updated_attributes
@topic.reload
expect(assigns(:topic)).to eq(3)
end
it 'redirects to admin topic path' do
patch :update, id: @topic, topic: updated_attributes
expect(response).to redirect_to(admin_topics_path)
end
end
context 'with invalid attributes' do
it 'does not update a topic'
it 're-renders the edit template'
end
end
describe 'GET #new' do
it 'renders the new template'
it 'creates a new topic'
end
describe 'PUT #create' do
context 'with valid attributes' do
it 'saves a topic in the database'
it 'redirects to created topic'
end
context 'without valid attributes' do
it 'does not save a topic in the database'
it 're-renders the new template'
end
end
describe 'DESTROY #delete' do
it 'finds a topic in the database'
it 'deletes a topic from the database'
it 'redirects to admin topics index'
end
end
end
管理员主题控制器:
class Admin::TopicsController < Admin::BaseController
def index
@topics = Topic.all
end
def show
@topic = Topic.find_by_id(params)
end
def edit
@topic = Topic.find_by_id(params)
@topic_options = Topic.all.collect { |topic| [ topic.category.name, topic.category_id ] }.uniq
end
def update
@topic = Topic.find_by_id(params)
if @topic.update(topic_params)
redirect_to admin_topic_path(@topic), notice: 'Topic updated successfully'
else
render :edit
end
end
private
def topic_params
params.require(:topic).permit(:subject, :body, :category_id)
end
end
有人可以指出我为什么测试失败并且应用程序运行正常的正确方向?
谢谢!