如何避免ActiveRecord :: InvalidForeignKey?

时间:2017-06-01 07:32:28

标签: ruby-on-rails activerecord rspec

我无法弄清楚如何修复RSpec错误。 我的应用是这样的。 有3个型号,CompanyBag,CompanyBagTarget,Company。 CompanyBag是一组公司。 CompanyBagTarget是CompanyBag和Company之间的关联表。 可能是,CompanyBagTarget与相应的公司不匹配。

现在,RSpec错误就在这里。

  1) CompanyBagsController POST #create creates a new ComapnyBag
     Failure/Error: t.save!

     ActiveRecord::InvalidForeignKey:
       Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`)): INSERT INTO `company_bag_targets` (`company_bag_id`, `company_id`, `display_order`) VALUES (38, 13, 0)
     # ./app/models/company_bag.rb:22:in `block in update_targets!'
     # ./app/models/company_bag.rb:16:in `each'
     # ./app/models/company_bag.rb:16:in `each_with_index'
     # ./app/models/company_bag.rb:16:in `update_targets!'
     # ./app/controllers/company_bags_controller.rb:52:in `create'
     # ./spec/controllers/company_bag_controller_spec.rb:55:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/company_bag_controller_spec.rb:54:in `block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # Mysql2::Error:
     #   Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`))
     #   ./app/models/company_bag.rb:22:in `block in update_targets!'

  2) CompanyBagsController POST #create creates a new ComapnyBagTarget
     Failure/Error: t.save!

     ActiveRecord::InvalidForeignKey:
       Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`)): INSERT INTO `company_bag_targets` (`company_bag_id`, `company_id`, `display_order`) VALUES (39, 13, 0)
     # ./app/models/company_bag.rb:22:in `block in update_targets!'
     # ./app/models/company_bag.rb:16:in `each'
     # ./app/models/company_bag.rb:16:in `each_with_index'
     # ./app/models/company_bag.rb:16:in `update_targets!'
     # ./app/controllers/company_bags_controller.rb:52:in `create'
     # ./spec/controllers/company_bag_controller_spec.rb:62:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/company_bag_controller_spec.rb:61:in `block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # Mysql2::Error:
     #   Cannot add or update a child row: a foreign key constraint fails (`eiicon`.`company_bag_targets`, CONSTRAINT `fk_bag_targets_company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`))
     #   ./app/models/company_bag.rb:22:in `block in update_targets!'

接下来是模型的定义。

class CompanyBag < ApplicationRecord
  has_many :targets, class_name: "CompanyBagTarget"
  def update_targets!(company_ids:)
    destroy_targets

    company_ids.reverse.each_with_index do |id, idex|
      t = CompanyBagTarget.new
      t.company_bag_id = self.id
      t.company_id = id
      t.display_order = idex

      t.save!
    end
  end


class CompanyBagTarget < ApplicationRecord
  belongs_to :company_target

接下来,这是控制器。

  def create
    @bag = CompanyBag.new(bag_params)
    @target_ids = params[:company_bag][:target_ids].split(",").map{|n| n.split("_")[0].to_i}

    if bag_params[:banner].present?
      filename = upload_image
      @bag.banner = filename
    end

    if @bag.save
      @bag.update_targets!(company_ids: @target_ids)
      redirect_to action: 'index'
    else
      flash[:alert] = @bag.errors.messages.values[0][0]
      @target_ids = params[:company_bag][:target_ids]
      render 'new'
    end
  end

最后,这是控制器的规格。

require 'rails_helper'

RSpec.describe CompanyBagsController, type: :controller do
  login_admin

  let(:user) { @admin }
  let(:company_bag) { FactoryGirl.create(:some_company_bag) }
  let(:company_bag_target) { {target_ids: "1_インテリジェンステスト株式会社,21_>グローバルウォーカーズ株式会社,33_株式会社コーデセブン"} }
  let(:companies) { FactoryGirl.create(:companies) }
  let(:valid_attributes) {
    {
      label: 1,
      banner: "https://s3-ap-northeast-1.amazonaws.com/eiicon.prd.contents/image/bags/6dbd5b5b-f242-4e4a-bcd3-de3edc9ae08d.png",
      title: "test title",
      description: "test title",
      target_ids: "1_インテリジェンステスト株式会社,21_グローバルウォーカーズ株>式会社,33_株式会社コーデセブン"
    }
  }
  describe 'POST #create' do
    it 'creates a new ComapnyBag' do
      expect{
        post :create, params: {company_bag: valid_attributes}, session: valid_session
      }.to change(CompanyBag, :count).by(1)
    end

    it 'creates a new ComapnyBagTarget' do
      expect{
        post :create, params: {company_bag: valid_attributes}, session: valid_session
      }.to change(CompanyBagTarget, :count).by(1)
    end

请任何人。提前谢谢。

[附录] 接下来,这是工厂。

FactoryGirl.define do
  factory :some_company_bag, class: CompanyBag do
      label "some label"
      banner "https://s3-ap-northeast-1.amazonaws.com/eiicon.prd.contents/image/bags/6dbd5b5b-f242-4e4a-bcd3-de3edc9ae08d.png"
      title "Best Company Title Ever!!"
      description "Some says description"
      html_description "Html desc"
      html_keyword "Html Kw"
  end
  factory :companies, class: Company do
    name "複数テスト会社"
    name_kana "フクスウテストカイシャ"
    premium_status "free"
    pr_status_id 0
    is_valid 1
    after(:create) do |c|
      c.staff << FactoryGirl.create(:staff, company_id: c.id)
    end
  end
end

表格。

  create_table "company_bag_targets", primary_key: ["company_bag_id", "company_id"], force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
    t.integer "company_bag_id", null: false
    t.integer "company_id",     null: false
    t.integer "display_order",  null: false
    t.index ["company_id"], name: "fk_bag_targets_company", using: :btree
  end

  create_table "company_bags", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
    t.string "label",            limit: 100,   null: false
    t.string "banner",           limit: 300
    t.string "title",            limit: 300
    t.text   "description",      limit: 65535
    t.string "html_description", limit: 300
    t.string "html_keyword",     limit: 300
  end

  create_table "company", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
    t.string   "name",                                                                         null: false
    t.string   "name_kana"
    t.integer  "prefecture_id"
    t.string   "url",                       limit: 1023
    t.date     "establishment"

0 个答案:

没有答案
相关问题