BatchDependentAssociations

Use dependent associations with Rails safely, with automatic batching.

You are viewing the README of version v0.2.0. You can find other releases here.

Branch Status
Release Build Status Coverage Status Gem Version Total Downloads
Development Build Status Coverage Status

As the discussion in this open Rails issue from 2015 points out dependent: :(destroy|delete_all) loads the entire relation and does not batch. This makes the usage of this otherwise great feature very dangerous and disencouraged at the very least because of possible OOM issues.

This gem is the sweet spot between the memory safety of custom batching and the convenience of letting Rails take care of associations. When included, it prepends a before_destroy hook that removes all has_many associations with appropriate dependent options. It will call destroy or delete if dependent is set to :destroy or :delete_all respectively. nullify and restrict_with_(error|exception) options don't remove associations. For the documentation of dependent options refer to Active Record Associations 4.2.2.4 (currently it incorrectly lists delete instead of delete_all).

Installation

Add this line to your application's Gemfile:

gem 'batch_dependent_associations'

And then execute:

$ bundle

Or install it yourself as:

$ gem install batch_dependent_associations

Usage

require "batch_dependent_associations"

class SafePerson < ActiveRecord::Base
  include BatchDependentAssociations

  has_many :bank_accounts, dependent: :destroy
  has_many :friends, dependent: :delete_all
end

Is equivalent to:

class SafePerson < ActiveRecord::Base
  has_many :bank_accounts, dependent: :destroy
  has_many :friends, dependent: :delete_all

  before_destroy :batch_dependent_associations, prepend: true

  def batch_dependent_associations
    bank_accounts.find_each(batch_size: 5, &:destroy)
    friends.find_each(batch_size: 5, &:delete)
  end
end

Custom batch size

Since v0.2.0

Can be set via the dependent_associations_batch_size class variable. Default is 1000 (same as Rails default).

class SafePerson < ActiveRecord::Base
  include BatchDependentAssociations
  self.dependent_associations_batch_size = 500
end

Development

git clone [email protected]:thisismydesign/batch_dependent_associations.git
bundle
RAILS_ENV=test bundle exec rake db:drop db:create db:migrate # Ignore schema.rb error: https://source.xing.com/growth/inquiry/pull/92
bundle exec rake

Feedback

Any feedback is much appreciated.

I can only tailor this project to fit use-cases I know about - which are usually my own ones. If you find that this might be the right direction to solve your problem too but you find that it's suboptimal or lacks features don't hesitate to contact me.

Please let me know if you make use of this project so that I can prioritize further efforts.

Conventions

This gem is developed using the following conventions:

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/thisismydesign/batch_dependent_associations.