ActiveRecord::InvalidForeignKey (Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails (`-app name-_development`.`-Intermediate table name-`, CONSTRAINT `fk_rails_~~~~~` FOREIGN KEY (`-Product table name-_id`) REFERENCES `-Product table name-` (`id`))):
I'm creating a flea market app like Mercari, and I've even implemented a function that allows you to tag and sell products using Form objects. Each model and controller looks like this
/app/model/item.rb
class Item < ApplicationRecord
  has_many :tag_item_relations
  has_many :tags, through: :tag_item_relations
end
/app/model/tag.rb
class Tag < ApplicationRecord
  has_many :tag_item_relations
  has_many :items, through: :tag_item_relations
  validates :tag_name, uniqueness: true
end
/app/model/tag_item_relation.rb
class TagItemRelation < ApplicationRecord
  belongs_to :item
  belongs_to :tag
end
/app/form/tags_item.rb
class TagsItem
  include ActiveModel::Model
  attr_accessor :item_name,
                :tag_name
  with_options presence: true do
    validates :item_name
  end
  def save
    item = Item.create(item_name: item_name)
    tag = Tag.where(tag_name: tag_name).first_or_initialize
    tag.save
    TagItemRelation.create(item_id: item.id, tag_id: tag.id)
  end
end
controller
/app/controller/items_controller.rb
class ItemsController < ApplicationController
  def index
    @items = Item.all.order('created_at ASC')
  end
  def new
    @item = TagsItem.new
  end
  def create
    @item = TagsItem.new(items_params)
    if @item.valid?
      @item.save
      redirect_to root_path
    else
      render :new
    end
  end
  private
  def items_params
    params.require(:tags_item).permit(
      :item_name,
      :tag_name
    )
  end
end
After that, with the product browsing function Implemented the problem __ product deletion function __
/app/controller/items_controller.rb
class ItemsController < ApplicationController
  before_action :set_item, only: [:show, :destroy]
###Omission
  def  show
    @tags_item = TagItemRelation.find(params[:id])
  end
  def destroy
    if current_user.id == @item.user_id
      @item.destroy
      redirect_to root_path
    else
      render :show
    end
  end
private
###Omission
  def set_item
    @item = Item.find(params[:id])
    @tag = Tag.find(params[:id])
  end
end
However, when I try to delete the items that I actually put up, ...
ActiveRecord::InvalidForeignKey (Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails (`-app name-_development`.`tag_item_relations`, CONSTRAINT `fk_rails_~~~~~~` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`))):
Error occurred and the product could not be deleted.
If you read the error details carefully, the product id is included in the __foreign key __ of the intermediate table. I can't delete or update! You can see that it is written
So when I looked up foreign keys ... Foreign keys (also known as foreign constraint keys) are database keys that are often written in migration files, etc. It prevents you from entering arbitrary values in specific items in the database, and has restrictions to select from external items. It seems that it mainly restricts __changes from the foreign key table to the data in the primary key table. In this case, you can see that the foreign key table is tag_item_relations and the primary key table is item.
The cause of this error was the foreign key (foreign_key: true) described in the migration file. However, if you rewrite the entire migration file, another problem may occur. This time I'm going to set dependent:: destroy to delete the item set as a foreign key in destory With this simple setting, you will be able to delete products without any problems.
/app/model/item.rb
class Item < ApplicationRecord
  has_many :tag_item_relations, foreign_key: :item_id, dependent: :destroy
  has_many :tags, through: :tag_item_relations
end
What is a foreign key? (https://wa3.i-3-i.info/word1992.html)
Because I was addicted to foreign key constraints (rails) Settings for destroying data with foreign keys
Recommended Posts