activerecord-nested_attribute_destruction
Build status for all matrix combinations listed in compatibility
TL;DR
class Harbor
has_many :ships
accepts_nested_attributes_for :ships, allow_destroy: true
end
harbor.ships_attributes = [harbor.ships.first.attributes.merge('_destroy': true)]
harbor.save!
harbor.ships_destroyed_during_save? # true
See that last line of code? That is what this gem adds :smiley:
Description
Active Record offers introspection of saved changes for almost everything you could want. The one thing I have repeatedly found myself wishing for was a way to know if a nested attribute was destroyed during save via accepts_nested_attributes.
The only way I know to find that information is to set a flag in a callback before saving, then use that flag for state comparison after the save completes.
This gem handles setting the flags before saving and adds introspection into the state after the save.
Installation
Add this line to your application's Gemfile:
gem 'activerecord-nested_attribute_destruction'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install activerecord-nested_attribute_destruction
Usage
API
When you call #accepts_nested_attributes_for
, this gem will automatically
install its hooks on the class. One method is also added to the class instance
API: <association_name>_destroyed_during_save?
.
For example:
has_many :ships
has_one :accountant
accepts_nested_attributes_for :ships, :accountant, allow_destroy: true
You can call ships_destroyed_during_save?
and
accountant_destroyed_during_save?
after a save to check if associated ships or
the accountant were destroyed through nested attribute assignment during the
save.
Example
Here is an example of how it works, adapted from the test suite.
def print_result(h)
if h.ships_destroyed_during_save?
puts "At least one ship was destroyed during the last save operation"
else
puts "No ships were destroyed during the last save operation"
end
end
harbor = DangerousHarbor.create(name: 'Blue Lagoon')
ship1 = (harbor.ships << Ship.create(harbor: harbor)).first
ship2 = (harbor.ships << Ship.create(harbor: harbor)).first
harbor.ships_attributes = [
ship1.attributes.merge('_destroy': true),
ship2.attributes.merge(fuel_remaining: 10)
]
harbor.save!
print_result(harbor)
harbor.save!
print_result(harbor)
and the output when the code above is run:
At least one ship was destroyed during the last save operation
No ships were destroyed during the last save operation
To see more examples, take a look at the tests.
Compatibility
This gem should be compatible with all versions of Ruby 2.3 and higher. It should be compatible with Active Record versions 5.2 and up.
Because of rubocop dependencies and keyword arguments changes in Ruby 3.0 which affected the database setup code used in the test suite, it is only tested against the matrices displayed below.
Sorted by Active Record version
Active Record version | Ruby Version |
---|---|
5.2 | 2.5 |
5.2 | 2.6 |
5.2 | 2.7 |
6.0 | 2.5 |
6.0 | 2.6 |
6.0 | 2.7 |
6.1 | 2.5 |
6.1 | 2.6 |
6.1 | 2.7 |
6.1 | 3.0 |
7.0 | 2.7 |
7.0 | 3.0 |
Sorted by Ruby version
Ruby Version | Active Record version |
---|---|
2.5 | 5.2 |
2.5 | 6.0 |
2.5 | 6.1 |
2.6 | 5.2 |
2.6 | 6.0 |
2.6 | 6.1 |
2.7 | 5.2 |
2.7 | 6.0 |
2.7 | 6.1 |
2.7 | 7.0 |
3.0 | 6.1 |
3.0 | 7.0 |
Specific requirements
Ruby
The safe navigation operator, introduced in Ruby 2.3, is used.
Active Record
The API changes in Active Record 5.2 are necessary for the core functionality of the gem.
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/brandoncc/activerecord-nested\_attribute\_destruction. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.