Can I set up Cascade deleting in Rails?
you can also set the :dependent option to :delete_all. :delete_all will issue a single SQL statement to delete all child records. because of this using :delete_all may give you better performance.
has_many :memberships, dependent: :delete_all
Adding cascade deletion in a rails
drop it and add it again (it's an index, no information is lost).
class ModifyTreeRefFromDogs < ActiveRecord::Migration
def change
remove_foreign_key "dog", "trees"
add_foreign_key "dog", "trees", on_delete: :cascade
end
end
Note: this seems to be a good reference for foreign keys in rails and includes exactly the on_delete code you tried: Foreign Keys in Rails 4.2
Rails: delete cascade vs dependent destroy
It really depends on the behavior you want. In case 1, destroy will be called on each associated order, and therefor so will the ActiveRecord callbacks. In case 2, these callbacks are not triggered, but it will be way faster and guarantees referential integrity.
In an application's infancy, I'd recommend going with :dependent => :destroy
because it lets you develop in a way that is independent of the database. Once you start to scale, you should start doing it in the database for performance/integrity reasons.
How to add column as foreign key with cascade delete in rails
Solution is ref_name should be singular
add_reference(:usages, :product, foreign_key: { on_delete: :cascade })
Cascade delete in Ruby ActiveRecord models?
Yes. On a Rails' model association you can specify the :dependent
option, which can take one of the following three forms:
:destroy/:destroy_all
The associated objects are destroyed alongside this object by calling theirdestroy
method:delete/:delete_all
All associated objects are destroyed immediately without calling their:destroy
method:nullify
All associated objects' foreign keys are set toNULL
without calling theirsave
callbacks
Note that the :dependent
option is ignored if you have a :has_many X, :through => Y
association set up.
So for your example you might choose to have a post delete all its associated comments when the post itself is deleted, without calling each comment's destroy
method. That would look like this:
class Post < ActiveRecord::Base
validates_presence_of :body, :title
has_many :comments, :dependent => :delete_all
end
Update for Rails 4:
In Rails 4, you should use :destroy
instead of :destroy_all
.
If you use :destroy_all
, you'll get the exception:
The :dependent option must be one of [:destroy, :delete_all, :nullify,
:restrict_with_error, :restrict_with_exception]
Option for Cascade Delete for References or On Delete
This should work
create_table :childs do |t|
t.references :parent, index: true, foreign_key: {on_delete: :cascade}
t.string :name
t.timestamps null: false
end
According to ActiveRecord::ConnectionAdapters::TableDefinition#references
, if a hash is specified on the foreign_key
option, it is directly passed down into the foreign_key
method.
source:
foreign_key(col.to_s.pluralize, foreign_key_options.is_a?(Hash) ? foreign_key_options : {}) if foreign_key_options
Is it possible to cascade active record deletion in batches?
You really just need to setup the foreign keys to cascade and Postgres will take care of deleting all the way down the line. Since this is implemented on the database layer it does not matter how you trigger the delete from Rails.
class CreateCountries < ActiveRecord::Migration[6.0]
def change
create_table :countries do |t|
t.string :name
t.timestamps
end
end
end
class CreateStates < ActiveRecord::Migration[6.0]
def change
create_table :states do |t|
t.string :name
t.belongs_to :country, null: false, foreign_key: {on_delete: :cascade}
t.timestamps
end
end
end
class CreateCities < ActiveRecord::Migration[6.0]
def change
create_table :cities do |t|
t.string :name
t.belongs_to :state, null: false, foreign_key: {on_delete: :cascade}
t.timestamps
end
end
end
Models:
class Country < ApplicationRecord
has_many :states
has_many :cities, through: :states
end
class State < ApplicationRecord
belongs_to :country
has_many :cities
end
class City < ApplicationRecord
belongs_to :state
has_one :country, through: :state
end
Passing spec:
require 'rails_helper'
RSpec.describe Country, type: :model do
describe "cascading delete" do
let!(:country){ Country.create }
let!(:state){ country.states.create }
let!(:city){ state.cities.create }
it "deletes the states" do
expect {
country.delete
}.to change(State, :count).from(1).to(0)
end
it "deletes the cities" do
expect {
Country.delete_all
}.to change(City, :count).from(1).to(0)
end
end
end
If you are using .each_with_batches
or not here is kind of irrelevant here. Anything that creates a DELETE FROM countries
query is going to fire that database trigger. Unless you really need to evaluate if each parent should be deleted in Rails you should just be able to do:
Country.where(evil: true).delete_all
This is going to be far more efficient then .find_each
as you're just doing one SQL query. If you iterate through the records you're doing one DELETE FROM coutries WHERE id = ?
query per row and since its blocking Rails has to wait for the round trip to the db.
How do I create a foreign key with a cascading delete constraint in my Rails 5 migration?
Seems like that ReferenceDefinition doesn't accept on_delete
option. You can specify on delete with add_foreign_key:
class CreateSearchCodeTable < ActiveRecord::Migration[5.0]
def change
create_table :search_codes do |t|
t.string :code
t.references :address, type: :string, index: true
t.index ["code"], name: "index_search_codes_on_code", unique: true, using: :btree
end
add_foreign_key :search_codes, :addresses, on_delete: :cascade
end
end
Related Topics
Rails I18N via Database Column
What Command Opens Ruby's Repl
-%>' (Minus Sign) at the End of a Erb Sequence
How to Make Carrierwave Delete the File When Destroying a Record
Fail VS. Raise in Ruby:Should We Really Believe the Style Guide
Ruby Open-Uri Redirect Forbidden
How to Use the Rails Helper "Distance_Of_Time_In_Words" in Plain Old Ruby (Non-Rails)
Rails - Get the Time Difference in Hours, Minutes and Seconds
Consistent String#Hash Based Only on the String's Content
How to Compare a String Against Multiple Other Strings
Rails Strip Non Numeric Values Before Save
The Encoding That Notepad++ Just Calls "Ansi", Does Anyone Know What to Call It for Ruby