[RUBY] How to delete only specific data from data created using Form object

The point

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`))):

Introduction

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.

What I looked up

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.

Foreign key setting change

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

Referenced site

What is a foreign key? (https://wa3.i-3-i.info/word1992.html)

Related article

Because I was addicted to foreign key constraints (rails) Settings for destroying data with foreign keys

Recommended Posts

How to delete only specific data from data created using Form object
[IOS] How to get data from DynamoDB
How to delete data with foreign key
[Rails] How to handle data using enum
How to delete a controller etc. using a command
How to create hierarchical category data using ancestry
How to delete custom Adapter elements using a custom model
[Java] How to erase a specific character from a character string
How to run only specific files with gem's rake test
How to create a form to select a date from the calendar
Map only specific columns to POJO by searching using Repository
[Rails] How to delete images uploaded by carrierwave (using devise)
How to exclude auto-generated from Jacoco coverage when using Lombok
[IOS14] How to get Data type image data directly from PHPickerViewController?
How to migrate from JUnit4 to JUnit5
How to authorize using graphql-ruby
[Rails 6] How to create a dynamic form input screen using cocoon
How to delete large amounts of data in Rails and concerns
How to get and add data from Firebase Firestore in Ruby
kotlin & Java: How to hide the toolbar only for specific fragments
How to push from Tarminal to GitHub
How to use Spring Data JDBC
[Rails] Various ways to delete data
[How to install Spring Data Jpa]
[Beginner] How to delete NO FILE
How to add the delete function
How to build CloudStack using Docker
How to change from HTML to Haml
How to return a value from Model to Controller using the [Swift5] protocol
How to limit IP address only to a specific directory with laravel + nginx
Try to get data from database using MyBatis in Micronaut + Kotlin project
[Java] How to get to the front of a specific string using the String class
How to compare only the time with Rails (from what time to what time, something like)