effective_trash 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5861ff673da253d2c1b764bad5f96c21c4ede0f
4
- data.tar.gz: 619b6e251bc29e258dfb2daddcb7e022a7efc4bd
3
+ metadata.gz: d48b6ae4a747e8d6d2567827966736aff26b6b53
4
+ data.tar.gz: e4eb0078becab79191be39d8bb2b0d94159e43f7
5
5
  SHA512:
6
- metadata.gz: 0cc1f9d9d136367ca6777e4f81733a4bc97e6518efee7f8186292a4eb106ae95c4f4f931350485f2d40eeb4369040904076316db05c9910cbc4016feaf267b8b
7
- data.tar.gz: 198377e4829662be812a8bdbb21eafd8b4e8432954a2311347afc45eb64d38ec7e6f926331d3efb89217e4df695d9f3fea898ce668e649884d9af37878aaa9e3
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.to_s}"
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)
@@ -28,8 +28,7 @@ module Effective
28
28
 
29
29
  Effective::Trash.transaction do
30
30
  begin
31
- @trash.restore_trash!
32
- @trash.destroy!
31
+ @trash.restore!
33
32
  flash[:success] = "Successfully restored #{@trash}"
34
33
  rescue => e
35
34
  flash[:danger] = "Unable to restore: #{e.message}"
@@ -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
- hash.map do |k, v|
15
- content_tag(:tr) do
16
- content_tag((options[:th] ? :th : :td), k) +
17
- content_tag(:td) do
18
- if v.kind_of?(Hash)
19
- tableize_hash(v, options.merge({:class => 'table table-bordered', :th => (options.key?(:sub_th) ? options[:sub_th] : options[:th])}))
20
- elsif v.kind_of?(Array)
21
- '[' + v.join(', ') + ']'
22
- else
23
- v.to_s
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.join('').html_safe
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 = Effective::Trash.new(
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', visible: false
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: true, sortable: false do |trash|
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 restore_trash!
31
+ def restore!
32
32
  raise 'no attributes to restore from' unless details.kind_of?(Hash) && details[:attributes].present?
33
- trashed_type.constantize.new(details[:attributes]).save!
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
@@ -1,3 +1,3 @@
1
1
  module EffectiveTrash
2
- VERSION = '0.2.1'.freeze
2
+ VERSION = '0.2.2'.freeze
3
3
  end
@@ -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.1
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-01-09 00:00:00.000000000 Z
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