Skip to content

Commit

Permalink
General improvements
Browse files Browse the repository at this point in the history
Simplify `discard` and `undiscard` methods
 - remove with_transaction_returning_status, run_callbacks shoudl return the result of the block
 - use update_attribute as no validation should be performed to discard (same as with destroy)

Scope `discard_all` to only kept records, `#discard` will not change them and this can save some ierations and help to return only affected records at the end of the query (more like `destroy_all`)

Scope `discard_all` to only discarded records, `#undiscard` will not change them and this can save some iterations and help to return only affected records at the end of the query (more like `destroy_all`)

Update README to clarify that save and update callbacks are run when discarding/undiscarding

Update travis ruby versions

Add .yardopts
  • Loading branch information
Gustavo Bazan committed Apr 18, 2018
1 parent abf3715 commit dfdd984
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 26 deletions.
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
sudo: false
language: ruby
rvm:
- 2.2.9
- 2.3.6
- 2.4.3
- 2.5.0
- 2.2.10
- 2.3.7
- 2.4.4
- 2.5.1
env:
matrix:
- RAILS_VERSION='~> 4.2.0'
Expand Down
8 changes: 8 additions & 0 deletions .yardopts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--protected
--no-private
--embed-mixin ClassMethods
-
README.md
CHANGELOG.md
CODE_OF_CONDUCT.md
LICENSE.txt
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ class Post < ActiveRecord::Base
end
```

*Warning:* Please note that callbacks for save and update are run when discarding/undiscarding a record

**Working with Devise**

A common use case is to apply discard to a User record. Even though a user has been discarded they can still login and continue their session.
Expand Down
2 changes: 1 addition & 1 deletion discard.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_dependency "activerecord", '>= 4.2', '< 6'
spec.add_dependency "activerecord", ">= 4.2", "< 6"
spec.add_development_dependency "bundler", "~> 1.14"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.5.0"
Expand Down
73 changes: 53 additions & 20 deletions lib/discard/model.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
module Discard
# Handles soft deletes of records.
#
# Options:
#
# - :discard_column - The columns used to track soft delete, defaults to `:discarded_at`.
module Model
extend ActiveSupport::Concern

Expand All @@ -15,41 +20,69 @@ module Model
define_model_callbacks :undiscard
end

# :nodoc:
module ClassMethods
# Discards the records by instantiating each
# record and calling its {#discard} method.
# Each object's callbacks are executed.
# Returns the collection of objects that were discarded.
#
# Note: Instantiation, callback execution, and update of each
# record can be time consuming when you're discarding many records at
# once. It generates at least one SQL +UPDATE+ query per record (or
# possibly more, to enforce your callbacks). If you want to discard many
# rows quickly, without concern for their associations or callbacks, use
# #update_all(discarded_at: Time.current) instead.
#
# ==== Examples
#
# Person.where(age: 0..18).discard_all
def discard_all
all.each(&:discard)
kept.each(&:discard)
end

# Undiscards the records by instantiating each
# record and calling its {#undiscard} method.
# Each object's callbacks are executed.
# Returns the collection of objects that were undiscarded.
#
# Note: Instantiation, callback execution, and update of each
# record can be time consuming when you're undiscarding many records at
# once. It generates at least one SQL +UPDATE+ query per record (or
# possibly more, to enforce your callbacks). If you want to undiscard many
# rows quickly, without concern for their associations or callbacks, use
# #update_all(discarded_at: nil) instead.
#
# ==== Examples
#
# Person.where(age: 0..18).undiscard_all
def undiscard_all
all.each(&:undiscard)
discarded.each(&:undiscard)
end
end

# @return [true,false] true if this record has been discarded, otherwise false
# @return [Boolean] true if this record has been discarded, otherwise false
def discarded?
!!self[self.class.discard_column]
self[self.class.discard_column].present?
end

# @return [true,false] true if successful, otherwise false
# Discard record
#
# @return [Boolean] true if successful, otherwise false
def discard
unless discarded?
with_transaction_returning_status do
run_callbacks(:discard) do
self[self.class.discard_column] = Time.current
save
end
end
return if discarded?
run_callbacks(:discard) do
update_attribute(self.class.discard_column, Time.current)
end
end

# @return [true,false] true if successful, otherwise false
# Undiscard record
#
# @return [Boolean] true if successful, otherwise false
def undiscard
if discarded?
with_transaction_returning_status do
run_callbacks(:undiscard) do
self[self.class.discard_column] = nil
save
end
end
return unless discarded?
run_callbacks(:undiscard) do
update_attribute(self.class.discard_column, nil)
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/discard/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module Discard
VERSION = "1.0.0"
# Discard version
VERSION = "1.0.0".freeze
end

0 comments on commit dfdd984

Please sign in to comment.