effective_trash 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -0
- data/app/controllers/admin/trash_controller.rb +1 -1
- data/app/controllers/effective/trash_controller.rb +1 -2
- data/app/helpers/effective_trash_helper.rb +15 -13
- data/app/models/concerns/acts_as_trashable.rb +1 -8
- data/app/models/effective/datatables/trash.rb +2 -2
- data/app/models/effective/trash.rb +18 -3
- data/db/trash/trash_archived_booleans.rb +28 -0
- data/lib/effective_trash/version.rb +1 -1
- data/lib/effective_trash.rb +13 -0
- data/lib/generators/effective_trash/trash_archived_booleans_generator.rb +25 -0
- metadata +18 -3
- data/lib/effective_trash/active_record_serializer.rb +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d48b6ae4a747e8d6d2567827966736aff26b6b53
|
4
|
+
data.tar.gz: e4eb0078becab79191be39d8bb2b0d94159e43f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ff0bc35b9b92526df5bd06991f872f57a5a831779524774490e353160f9cc06c7ed6e46077e4d284d3af8e5a3ace5f5a47d814f540eec77c52a40998b5f9dd1
|
7
|
+
data.tar.gz: 208dfa88a8522b943c9135e138a5040ce58916bc2ac21e11bb6609145e20e047244562847fa833e9690896a271a63d2778831d62159fd5f9c265e7e1f1538dfd
|
data/README.md
CHANGED
@@ -81,6 +81,23 @@ can :admin, :effective_trash
|
|
81
81
|
|
82
82
|
The user must be permitted to to `:update` an `Effective::Trash` in order to restore the trashed item.
|
83
83
|
|
84
|
+
## Upgrade database from archived booleans
|
85
|
+
|
86
|
+
Use the following generator, to produce a database migration:
|
87
|
+
|
88
|
+
```
|
89
|
+
rails generate effective_trash:trash_archived_booleans
|
90
|
+
```
|
91
|
+
|
92
|
+
The migration will trash all `archived?` objects, delete them, and replace the archived boolean on the corresponding database table.
|
93
|
+
|
94
|
+
This upgrades from this gem author's previous archived implementation, which was:
|
95
|
+
|
96
|
+
- Use an `archived` boolean on each model.
|
97
|
+
- Call the model by a scope (or default scope, yuck) somehting like `Post.where(archived: false)`.
|
98
|
+
|
99
|
+
Don't do that.
|
100
|
+
|
84
101
|
## License
|
85
102
|
|
86
103
|
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
@@ -18,7 +18,7 @@ module Admin
|
|
18
18
|
|
19
19
|
def show
|
20
20
|
@trash = Effective::Trash.all.find(params[:id])
|
21
|
-
@page_title = "Trash item - #{@trash.
|
21
|
+
@page_title = "Trash item - #{@trash.trashed_to_s}"
|
22
22
|
|
23
23
|
EffectiveTrash.authorized?(self, :show, @trash)
|
24
24
|
EffectiveTrash.authorized?(self, :admin, :effective_trash)
|
@@ -10,21 +10,23 @@ module EffectiveTrashHelper
|
|
10
10
|
# Any other options are sent to the table tag
|
11
11
|
def tableize_hash(hash, options = {})
|
12
12
|
if hash.present? && hash.kind_of?(Hash)
|
13
|
-
content_tag(:table, options) do
|
14
|
-
|
15
|
-
|
16
|
-
content_tag(
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
content_tag(:table, class: options[:class]) do
|
14
|
+
content_tag(:tbody) do
|
15
|
+
hash.map do |k, v|
|
16
|
+
content_tag(:tr) do
|
17
|
+
content_tag((options[:th] ? :th : :td), k) +
|
18
|
+
content_tag(:td) do
|
19
|
+
if v.kind_of?(Hash)
|
20
|
+
tableize_hash(v, options.merge({class: 'table table-hover', th: (options.key?(:sub_th) ? options[:sub_th] : options[:th])}))
|
21
|
+
elsif v.kind_of?(Array)
|
22
|
+
'[' + v.join(', ') + ']'
|
23
|
+
else
|
24
|
+
v.to_s
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
|
-
end
|
27
|
-
end
|
28
|
+
end.join('').html_safe
|
29
|
+
end
|
28
30
|
end.html_safe
|
29
31
|
else
|
30
32
|
hash.to_s.html_safe
|
@@ -17,14 +17,7 @@ module ActsAsTrashable
|
|
17
17
|
has_one :trash, as: :trashed, class_name: Effective::Trash
|
18
18
|
|
19
19
|
before_destroy do
|
20
|
-
trash
|
21
|
-
trashed: self,
|
22
|
-
user: EffectiveTrash.current_user,
|
23
|
-
trashed_to_s: to_s,
|
24
|
-
trashed_extra: (trashed_extra if respond_to?(:trashed_extra)),
|
25
|
-
|
26
|
-
details: EffectiveTrash::ActiveRecordSerializer.new(self, acts_as_trashable_options).attributes
|
27
|
-
).save!
|
20
|
+
EffectiveTrash.trash!(self)
|
28
21
|
end
|
29
22
|
|
30
23
|
# Parse Options
|
@@ -11,14 +11,14 @@ if defined?(EffectiveDatatables)
|
|
11
11
|
table_column :id, visible: false
|
12
12
|
|
13
13
|
unless attributes[:user_id] || attributes[:user] || (attributes[:user] == false)
|
14
|
-
table_column :user, label: 'Destroyed by'
|
14
|
+
table_column :user, label: 'Destroyed by'
|
15
15
|
end
|
16
16
|
|
17
17
|
table_column :trashed_type, label: 'Type'
|
18
18
|
table_column :trashed_id, label: 'Original Id', visible: false
|
19
19
|
table_column :trashed_to_s, label: 'Item'
|
20
20
|
|
21
|
-
table_column :details, visible:
|
21
|
+
table_column :details, visible: false, sortable: false do |trash|
|
22
22
|
tableize_hash(trash.details, th: true, sub_th: false, width: '100%')
|
23
23
|
end
|
24
24
|
|
@@ -19,7 +19,7 @@ module Effective
|
|
19
19
|
default_scope -> { order(updated_at: :desc) }
|
20
20
|
|
21
21
|
def to_s
|
22
|
-
[trashed_type, trashed_id].join(' ').presence || 'New Trash item'
|
22
|
+
trashed_to_s.presence || [trashed_type, trashed_id].join(' ').presence || 'New Trash item'
|
23
23
|
end
|
24
24
|
|
25
25
|
def details
|
@@ -28,9 +28,24 @@ module Effective
|
|
28
28
|
|
29
29
|
# So this is a Trash item
|
30
30
|
# When we delete ourselves, we restore this trash item first
|
31
|
-
def
|
31
|
+
def restore!
|
32
32
|
raise 'no attributes to restore from' unless details.kind_of?(Hash) && details[:attributes].present?
|
33
|
-
|
33
|
+
|
34
|
+
resource = Effective::Resource.new(trashed_type)
|
35
|
+
object = trashed_type.constantize.new(details[:attributes])
|
36
|
+
|
37
|
+
resource.nested_resources.each do |association|
|
38
|
+
if details[association.name].present? && object.respond_to?("#{association.name}_attributes=")
|
39
|
+
nested_attributes = details[association.name].inject({}) do |h, (index, nested)|
|
40
|
+
h[index] = nested[:attributes].except('id', association.inverse_of.foreign_key); h
|
41
|
+
end
|
42
|
+
|
43
|
+
object.send("#{association.name}_attributes=", nested_attributes)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
object.save!(validate: false)
|
48
|
+
destroy!
|
34
49
|
end
|
35
50
|
|
36
51
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class TrashArchivedBooleans < ActiveRecord::Migration[4.2]
|
2
|
+
def self.up
|
3
|
+
Rails.application.eager_load!
|
4
|
+
klasses = ActiveRecord::Base.descendants
|
5
|
+
.reject { |klass| klass.abstract_class? }
|
6
|
+
.select { |klass| (klass.new.respond_to?(:archived?) rescue false) }
|
7
|
+
|
8
|
+
klasses.each do |klass|
|
9
|
+
puts "Trashing #{klass.table_name}"
|
10
|
+
|
11
|
+
ids = [] # to delete
|
12
|
+
|
13
|
+
klass.unscoped.where(archived: true).find_each do |resource|
|
14
|
+
print '.'
|
15
|
+
EffectiveTrash.trash!(resource)
|
16
|
+
ids << resource.id
|
17
|
+
end
|
18
|
+
|
19
|
+
klass.where(id: ids).delete_all
|
20
|
+
end
|
21
|
+
|
22
|
+
klasses.each { |klass| remove_column(klass.table_name, :archived) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.down
|
26
|
+
raise 'TODO: this could be written'
|
27
|
+
end
|
28
|
+
end
|
data/lib/effective_trash.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'haml-rails'
|
2
|
+
require 'effective_resources'
|
2
3
|
require 'effective_trash/engine'
|
3
4
|
require 'effective_trash/version'
|
4
5
|
|
@@ -31,4 +32,16 @@ module EffectiveTrash
|
|
31
32
|
@effective_trash_current_user
|
32
33
|
end
|
33
34
|
|
35
|
+
# Trash it - Does not delete the original object.
|
36
|
+
# This is run in a before_destroy, or through a script.
|
37
|
+
def self.trash!(obj)
|
38
|
+
trash = Effective::Trash.new(
|
39
|
+
trashed: obj,
|
40
|
+
user: EffectiveTrash.current_user,
|
41
|
+
trashed_to_s: obj.to_s,
|
42
|
+
trashed_extra: (trashed_extra if obj.respond_to?(:trashed_extra)),
|
43
|
+
details: Effective::Resource.new(obj).instance_attributes
|
44
|
+
).save!
|
45
|
+
end
|
46
|
+
|
34
47
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# bundle exec rails generate effective_trash:trash_archived_booleans
|
2
|
+
|
3
|
+
module EffectiveTrash
|
4
|
+
module Generators
|
5
|
+
class TrashArchivedBooleansGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
desc 'Upgrade all tables from boolean archived implementation. Trash all previously archived records'
|
9
|
+
|
10
|
+
source_root File.expand_path('../../template', __FILE__)
|
11
|
+
|
12
|
+
def self.next_migration_number(dirname)
|
13
|
+
if not ActiveRecord::Base.timestamped_migrations
|
14
|
+
Time.new.utc.strftime('%Y%m%d%H%M%S')
|
15
|
+
else
|
16
|
+
'%.3d' % (current_migration_number(dirname) + 1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_migration_file
|
21
|
+
migration_template ('../' * 3) + 'db/trash/trash_archived_booleans.rb', 'db/migrate/trash_archived_booleans.rb'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_trash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 2.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: effective_resources
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: coffee-rails
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,12 +119,13 @@ files:
|
|
105
119
|
- config/effective_trash.rb
|
106
120
|
- config/routes.rb
|
107
121
|
- db/migrate/01_create_effective_trash.rb.erb
|
122
|
+
- db/trash/trash_archived_booleans.rb
|
108
123
|
- lib/effective_trash.rb
|
109
|
-
- lib/effective_trash/active_record_serializer.rb
|
110
124
|
- lib/effective_trash/engine.rb
|
111
125
|
- lib/effective_trash/set_current_user.rb
|
112
126
|
- lib/effective_trash/version.rb
|
113
127
|
- lib/generators/effective_trash/install_generator.rb
|
128
|
+
- lib/generators/effective_trash/trash_archived_booleans_generator.rb
|
114
129
|
homepage: https://github.com/code-and-effect/effective_trash
|
115
130
|
licenses:
|
116
131
|
- MIT
|
@@ -1,61 +0,0 @@
|
|
1
|
-
module EffectiveTrash
|
2
|
-
class ActiveRecordSerializer
|
3
|
-
attr_accessor :resource, :options
|
4
|
-
|
5
|
-
def initialize(resource, options = {})
|
6
|
-
raise ArgumentError.new('options must be a Hash') unless options.kind_of?(Hash)
|
7
|
-
|
8
|
-
@resource = resource
|
9
|
-
@options = options
|
10
|
-
end
|
11
|
-
|
12
|
-
def attributes
|
13
|
-
attributes = { attributes: resource.attributes }
|
14
|
-
|
15
|
-
# Collect to_s representations of all belongs_to associations
|
16
|
-
(resource.class.try(:reflect_on_all_associations, :belongs_to) || []).each do |association|
|
17
|
-
attributes[association.name] = resource.send(association.name).to_s.presence
|
18
|
-
end
|
19
|
-
|
20
|
-
# Collect to_s representations for all has_one associations
|
21
|
-
(resource.class.try(:reflect_on_all_associations, :has_one) || []).each do |association|
|
22
|
-
next if association.name == :trash && resource.respond_to?(:acts_as_trashable_options) # We skip our own association
|
23
|
-
attributes[association.name] = resource.send(association.name).to_s.presence
|
24
|
-
end
|
25
|
-
|
26
|
-
# Collects attributes for all accepts_as_nested_parameters has_many associations
|
27
|
-
(resource.class.try(:reflect_on_all_autosave_associations) || []).each do |association|
|
28
|
-
attributes[association.name] = {}
|
29
|
-
|
30
|
-
Array(resource.send(association.name)).each_with_index do |child, index|
|
31
|
-
attributes[association.name][index+1] = ActiveRecordLogger.new(child, options).attributes
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
attributes.delete_if { |k, v| v.blank? }
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
# TODO: Make this work better with nested objects
|
41
|
-
def applicable(attributes)
|
42
|
-
atts = if options[:only].present?
|
43
|
-
attributes.slice(*options[:only])
|
44
|
-
elsif options[:except].present?
|
45
|
-
attributes.except(*options[:except])
|
46
|
-
else
|
47
|
-
attributes.except(:updated_at, :created_at)
|
48
|
-
end
|
49
|
-
|
50
|
-
(options[:additionally] || []).each do |attribute|
|
51
|
-
value = (resource.send(attribute) rescue :effective_trash_nope)
|
52
|
-
next if attributes[attribute].present? || value == :effective_trash_nope
|
53
|
-
|
54
|
-
atts[attribute] = value
|
55
|
-
end
|
56
|
-
|
57
|
-
atts
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|