animator 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7144168dc13c07de16022b09f83439081574c8fb
4
+ data.tar.gz: 6af7fba48b1b1eecce204e61d68f153958134301
5
+ SHA512:
6
+ metadata.gz: 0b6a06284fb6e0642531b53b2f2cca59fd1360241f58c28340624181e20731284e57a3d5297a5059e3a5f34b52e242ce512f58e2189b2a32e08f48a545563771
7
+ data.tar.gz: 1f34b0ef28dfb97a39bb5d0d3379f91d941ba31d1c14183ff1c0d50197fd45450db395d3b4af2d4059bda7bfb02264056f05e3fc0334e4e2adf286b4debf2b58
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Alec Larsen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,25 @@
1
+ Animator
2
+ ========
3
+ Inspired by the elegance of [PaperTrail](https://github.com/airblade/paper_trail), Animator is a cleanly namespaced ActiveRecord plugin that hooks into the existing model life-cycle allowing you to to restore (`Animable#reanimate`), query (`Animable.inanimate`), and inspect (`Animable#divine`) destroyed objects including associations without the tedium and ugliness of default scopes, monkey-patched methods, and complex callbacks.
4
+
5
+ ## Getting Started
6
+ Animator is opinionated software that protects every model in the application right out of the box.
7
+
8
+ Add it to your `Gemfile` and run the `bundle` command.
9
+ ```ruby
10
+ gem 'animator'
11
+ ```
12
+
13
+ Once the gem is installed, run the `animator:install` generator to create the necessary migration and default initializer.
14
+ ```console
15
+ rails g animator:install
16
+ ```
17
+
18
+ > **Note:** To selectively enable Animator, delete the initializer in `config/initializers/animator.rb` and include `Animator::Animable` on the desired models manually.
19
+
20
+ Finally, the database must be migrated to create the `eraminhos` table before Animator will work properly.
21
+ ```console
22
+ rake db:migrate
23
+ ```
24
+
25
+ > **Note:** In the very unlikely event that `eraminhos` needs to be preserved for use in the application, Animator may be configured to use an alternative table name by editing the migration and appending `Animator::Eraminho.table_name = 'alternative_table_name_for_eraminhos'` to the initializer.
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'animator'
3
+ s.version = '0.0.4'
4
+ s.platform = Gem::Platform::RUBY
5
+ s.summary = 'Animator is a cleanly namespaced ActiveRecord plugin that hooks into the existing model life-cycle allowing you to to restore (Animable#reanimate), query (Animable.inanimate), and inspect (Animable#divine) destroyed objects including associations without the tedium and ugliness of default scopes, monkey-patched methods, and complex callbacks.'
6
+ s.description = s.summary
7
+ s.homepage = 'https://github.com/AlecLarsen/animator'
8
+ s.authors = ['Alec Larsen']
9
+ s.email = 'aleclarsen42@gmail.com'
10
+ s.license = 'MIT'
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.require_paths = ['lib']
16
+
17
+ s.required_rubygems_version = '>= 1.3.6'
18
+
19
+ s.add_dependency 'activerecord', ['>= 3.0', '< 5.0']
20
+ s.add_dependency 'activesupport', ['>= 3.0', '< 5.0']
21
+
22
+ s.post_install_message = <<-eos
23
+
24
+ Animator will not work properly until the eraminhos table has been created. You can generate the proper migration by running `rails g animator:install`.
25
+
26
+ eos
27
+ end
@@ -0,0 +1,7 @@
1
+ require 'animator/eraminho'
2
+ require 'animator/animable'
3
+ require 'animator/fey_relation'
4
+ require 'animator/reanimation_error'
5
+
6
+ module Animator
7
+ end
@@ -0,0 +1,117 @@
1
+ module Animator
2
+ module Animable
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def reanimate!(id, options = {})
7
+ Eraminho.find_by!(animable_class: name, animable_id: id).animable!.reanimate!(options)
8
+ end
9
+
10
+ def reanimate(id, options = {})
11
+ reanimate!(id, options) rescue nil
12
+ end
13
+
14
+ def divine(id, options = {}, &block)
15
+ options = { validate: false }.merge(options)
16
+
17
+ result = nil
18
+
19
+ transaction do
20
+ instance = reanimate!(id, options)
21
+ result = instance.instance_exec(&block)
22
+ raise ActiveRecord::Rollback
23
+ end
24
+
25
+ result
26
+ end
27
+
28
+ def inanimate(transaction_uuid = nil, relation = all)
29
+ FeyRelation.new(relation.klass, transaction_uuid).merge(relation)
30
+ end
31
+ end
32
+
33
+ def divine(options = {}, &block)
34
+ options = { validate: false }.merge(options)
35
+
36
+ result = nil
37
+ eraminho = @eraminho
38
+ destroyed = @destroyed
39
+
40
+ transaction do
41
+ reanimate!(options)
42
+ result = instance_exec(&block)
43
+ raise ActiveRecord::Rollback
44
+ end
45
+
46
+ @eraminho = eraminho
47
+ @destroyed = destroyed
48
+ result
49
+ end
50
+
51
+ def animable?
52
+ destroyed? && !@eraminho.nil?
53
+ end
54
+
55
+ def reanimate!(options = {}, validation_queue = nil)
56
+ klass = self.class
57
+ options = { force: false, transactional: true, validate: true }.merge(options)
58
+
59
+ raise(ReanimationError, "#{inspect} is not animable.") unless animable?
60
+
61
+ transaction do
62
+ if validation_queue
63
+ run_callbacks(:reanimate) do
64
+ if options[:transactional]
65
+ Eraminho.with_transaction_uuid(@eraminho.transaction_uuid).find_each do |eraminho|
66
+ if options[:force]
67
+ eraminho.animable!.reanimate(options.merge(transactional: false, force: false), validation_queue)
68
+ else
69
+ eraminho.animable!.reanimate!(options.merge(transactional: false, force: false), validation_queue)
70
+ end
71
+ end
72
+ else
73
+ klass.unscoped.insert arel_attributes_with_values_for_create attribute_names
74
+ validation_queue << self if options[:validate]
75
+ @eraminho.delete
76
+ end
77
+ end
78
+
79
+ @eraminho = nil
80
+ @destroyed = false
81
+ else
82
+ validation_queue = []
83
+
84
+ reanimate!(options, validation_queue)
85
+
86
+ validation_queue.each do |animable|
87
+ unless animable.valid?(:reanimate)
88
+ raise(ActiveRecord::RecordInvalid.new(animable))
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ self
95
+ end
96
+
97
+ def reanimate(options = {}, validation_queue = nil)
98
+ reanimate!(options, validation_queue) rescue self
99
+ end
100
+
101
+ def eraminho
102
+ @eraminho
103
+ end
104
+
105
+ included do
106
+ define_callbacks :reanimate
107
+
108
+ around_destroy do |animable, &block|
109
+ block.call
110
+
111
+ unless animable?
112
+ @eraminho = Eraminho.create!(animable: animable)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,51 @@
1
+ require 'securerandom'
2
+ require 'yaml'
3
+
4
+ module Animator
5
+ class Eraminho < ActiveRecord::Base
6
+ scope :with_animable_id, ->(animable_id) { where(animable_id: animable_id) }
7
+ scope :with_animable_class, ->(animable_class) { where(animable_class: animable_class) }
8
+
9
+ scope :with_animable_attribute, ->(attribute_name, value) { where(arel_table[:anima].matches("% #{YAML.dump(attribute_name.to_s => value).gsub(/^---\n/, '')}%")) }
10
+ scope :with_animable_attributes, ->(attributes) { attributes.to_a.reduce(all) { |relation, key_value_pair| relation.with_animable_attribute(*key_value_pair) } }
11
+
12
+ scope :with_transaction_uuid, ->(transaction_uuid) { where(transaction_uuid: transaction_uuid) }
13
+
14
+ def animable=(animable)
15
+ if animable
16
+ raise(TypeError, "Attempted to set #{animable.inspect} as the animable of an Eraminho, but #{animable.class.name} has not included Animator::Animable") unless animable.is_a?(Animable)
17
+
18
+ self.animable_class = animable.class.name
19
+ self.animable_id = animable[animable.class.primary_key] if animable.class.primary_key
20
+ self.transaction_uuid = get_current_transaction_uuid(animable.class.connection)
21
+ self.anima = YAML.dump(animable)
22
+ end
23
+
24
+ @animable = animable
25
+ end
26
+
27
+ def animable
28
+ animable! rescue nil
29
+ end
30
+
31
+ def animable!
32
+ unless @animable
33
+ animable_class.constantize rescue nil # This is required because of ActiveSupport's lazy loading
34
+ @animable = YAML.load(anima)
35
+
36
+ raise(ReanimationError, "#{@animable.class.name} has not included Animator::Animable") unless @animable.is_a?(Animable)
37
+
38
+ @animable.instance_variable_set(:@destroyed, true)
39
+ @animable.instance_variable_set(:@eraminho, self)
40
+ end
41
+
42
+ @animable
43
+ end
44
+
45
+ private
46
+
47
+ def get_current_transaction_uuid(connection)
48
+ connection.current_transaction.instance_eval { @__animator_transaction_uuid__ ||= SecureRandom.uuid }
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,249 @@
1
+ module Animator
2
+ class FeyRelation
3
+ attr_reader :transaction_uuid
4
+ attr_reader :where_values_hash
5
+ attr_reader :klass
6
+
7
+ def initialize(klass, transaction_uuid = nil, where_values_hash = {}, &block)
8
+ @transaction_uuid = transaction_uuid
9
+ @where_values_hash = where_values_hash
10
+ @klass = klass
11
+
12
+ instance_exec(&block) if block
13
+ end
14
+
15
+ def spawn(&block)
16
+ self.class.new(@klass, @transaction_uuid, @where_values_hash, &block)
17
+ end
18
+
19
+ def where(where_values_hash, &block)
20
+ self.class.new(@klass, @transaction_uuid, @where_values_hash.merge(where_values_hash), &block)
21
+ end
22
+
23
+ def merge(relation)
24
+ if relation.is_a?(ActiveRecord::Relation)
25
+ raise(NotImplementedError, "#{self.class.name} does not support joins.") if relation.joins_values.any? || relation.includes_values.any? || relation.joined_includes_values.any?
26
+ raise(NotImplementedError, "#{self.class.name} does not support custom select.") if relation.select_values.any?
27
+ raise(NotImplementedError, "#{self.class.name} does not support aggragation.") if relation.group_values.any? || relation.having_values.any?
28
+ end
29
+
30
+ if relation.respond_to?(:klass, false)
31
+ raise('Class mismatch while attempting to merge into #{self.class.name}') unless relation.klass == @klass
32
+ end
33
+
34
+ where(relation.where_values_hash) do
35
+ @limit_value = relation.limit_value if relation.respond_to?(:limit_value, false)
36
+ @offset_value = relation.offset_value if relation.respond_to?(:offset_value, false)
37
+ end
38
+ end
39
+
40
+ def all
41
+ spawn
42
+ end
43
+
44
+ def to_a
45
+ eraminho_relation.map(&:animable)
46
+ end
47
+
48
+ def take
49
+ eraminho_relation.take.try(:animable)
50
+ end
51
+
52
+ def take!
53
+ take || raise(ActiveRecord::RecordNotFound)
54
+ end
55
+
56
+ def find_by(where_values_hash)
57
+ where(where_values_hash).take
58
+ end
59
+
60
+ def find_by!(where_values_hash)
61
+ where(where_values_hash).take!
62
+ end
63
+
64
+ def find(id)
65
+ find_by!(@klass.primary_key => id)
66
+ end
67
+
68
+ def first(limit = nil)
69
+ if limit
70
+ eraminho_relation.first(limit).map(&:animable)
71
+ else
72
+ eraminho_relation.first.try(:animable)
73
+ end
74
+ end
75
+
76
+ def first!
77
+ first || raise(ActiveRecord::RecordNotFound)
78
+ end
79
+
80
+ def last(limit = nil)
81
+ if limit
82
+ eraminho_relation.last(limit).map(&:animable)
83
+ else
84
+ eraminho_relation.last.try(:animable)
85
+ end
86
+ end
87
+
88
+ def last!
89
+ last || raise(ActiveRecord::RecordNotFound)
90
+ end
91
+
92
+ def exists?(where_values_hash = nil)
93
+ if where_values_hash
94
+ where(where_values_hash).exists?
95
+ else
96
+ eraminho_relation.exists?
97
+ end
98
+ end
99
+
100
+ def count
101
+ eraminho_relation.count
102
+ end
103
+
104
+ def pluck(*columns)
105
+ if columns.count > 1
106
+ eraminho_relation.map { |eraminho| columns.map { |column| eraminho.animable!.public_send(column) } }
107
+ else
108
+ eraminho_relation.map { |eraminho| eraminho.animable!.public_send(columns.first) }
109
+ end
110
+ end
111
+
112
+ def limit(limit_value)
113
+ spawn do
114
+ @limit_value = limit_value
115
+ end
116
+ end
117
+
118
+ def offset(offset_value)
119
+ spawn do
120
+ @offset_value = offset_value
121
+ end
122
+ end
123
+
124
+ def ids
125
+ eraminho_relation.pluck(:animable_id)
126
+ end
127
+
128
+ def find_each(options = {}, &block)
129
+ eraminho_relation.find_each(options) { |eraminho| block.call(eraminho.animable!) }
130
+ end
131
+
132
+ def reset
133
+ eraminho_relation.reset
134
+ end
135
+
136
+ def loaded?
137
+ eraminho_relation.loaded?
138
+ end
139
+
140
+ def inspect
141
+ entries = to_a.take(11).map!(&:inspect)
142
+ entries[10] = '...' if entries.size == 11
143
+
144
+ "#<#{self.class.name} [#{entries.join(', ')}]>"
145
+ end
146
+
147
+ def ==(other)
148
+ case other
149
+ when FeyRelation
150
+ eraminho_relation.to_sql == other.eraminho_relation.to_sql
151
+ when Array
152
+ to_a == other
153
+ end
154
+ end
155
+
156
+ def reanimate_all!(options = {})
157
+ options = { force: false, transactional: true, validate: true }.merge(options)
158
+
159
+ validation_queue = []
160
+
161
+ Eraminho.transaction do
162
+ if options[:transactional]
163
+ Eraminho.with_transaction_uuid(eraminho_relation.pluck(:transaction_uuid))
164
+ else
165
+ eraminho_relation
166
+ end.find_each do |eraminho|
167
+ if options[:force]
168
+ eraminho.animable!.reanimate(options.merge(transactional: false, force: false), validation_queue)
169
+ else
170
+ eraminho.animable!.reanimate!(options.merge(transactional: false, force: false), validation_queue)
171
+ end
172
+ end
173
+
174
+ validation_queue.each do |animable|
175
+ unless animable.valid?(:reanimate)
176
+ raise(ActiveRecord::RecordInvalid.new(animable))
177
+ end
178
+ end
179
+
180
+ reset
181
+ end
182
+
183
+ true
184
+ end
185
+
186
+ def reanimate_all(options = {})
187
+ reanimate_all! rescue false
188
+ end
189
+
190
+ def to_active_record_relation
191
+ @_active_record_relation ||= @klass.where(@where_values_hash)
192
+ end
193
+
194
+ def divine(options = {}, &block)
195
+ options = { validate: false }.merge(options)
196
+
197
+ result = nil
198
+
199
+ @klass.transaction do
200
+ reanimate_all!(options)
201
+ result = to_active_record_relation.instance_exec(&block)
202
+ raise ActiveRecord::Rollback
203
+ end
204
+
205
+ result
206
+ end
207
+
208
+ def respond_to_missing?(method_name, include_private = false)
209
+ @klass.respond_to?(method_name, false) || [].respond_to?(method_name, false) || super
210
+ end
211
+
212
+ def method_missing(method_name, *args, &block)
213
+ if @klass.respond_to?(method_name, false)
214
+ result = to_active_record_relation.public_send(method_name, *args, &block)
215
+
216
+ if result.respond_to?(:where_values_hash)
217
+ result = merge(result)
218
+ else
219
+ result
220
+ end
221
+ elsif [].respond_to?(method_name, false)
222
+ to_a.public_send(method_name, *args, &block)
223
+ else
224
+ super
225
+ end
226
+ end
227
+
228
+ protected
229
+
230
+ def eraminho_relation
231
+ unless @eraminho_relation
232
+ @eraminho_relation = Eraminho.with_animable_class(@klass.name)
233
+
234
+ @eraminho_relation = @eraminho_relation.with_transaction_uuid(@transaction_uuid) if @transaction_uuid
235
+
236
+ animable_id = @where_values_hash[@klass.primary_key] || @where_values_hash[@klass.primary_key.to_sym]
237
+ animable_attributes = @where_values_hash.reject { |key| key == @klass.primary_key || key == @klass.primary_key.to_sym }
238
+
239
+ @eraminho_relation = @eraminho_relation.with_animable_id(animable_id) if animable_id
240
+ @eraminho_relation = @eraminho_relation.with_animable_attributes(animable_attributes)
241
+
242
+ @eraminho_relation = @eraminho_relation.limit(@limit_value) if @limit_value
243
+ @eraminho_relation = @eraminho_relation.offset(@offset_value) if @offset_value
244
+ end
245
+
246
+ @eraminho_relation
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,4 @@
1
+ module Animator
2
+ class ReanimationError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,27 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/active_record'
3
+
4
+ module Animator
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ include ::Rails::Generators::Migration
7
+
8
+ def self.next_migration_number(dirname)
9
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
10
+ end
11
+
12
+ source_root File.expand_path('../templates', __FILE__)
13
+
14
+ def create_migration_file
15
+ migration_template 'create_eraminhos.rb', 'db/migrate/create_eraminhos.rb'
16
+ create_file_template 'animator.rb', 'config/initializers/animator.rb'
17
+ end
18
+
19
+ private
20
+
21
+ def create_file_template(source, destination)
22
+ source = File.expand_path(find_in_source_paths(source.to_s))
23
+ context = instance_eval('binding')
24
+ create_file(destination, ERB.new(::File.binread(source), nil, '-', '@output_buffer').result(context))
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ class ActiveRecord::Base
2
+ include Animator::Animable
3
+ end
@@ -0,0 +1,15 @@
1
+ class CreateEraminhos < ActiveRecord::Migration
2
+ def change
3
+ create_table :eraminhos do |t|
4
+ t.string :transaction_uuid, null: false
5
+ t.string :animable_class, null: false
6
+ t.integer :animable_id, null: true # Support for tables without a primary key
7
+ t.text :anima, null: false
8
+ t.datetime :created_at, null: false
9
+ end
10
+
11
+ add_index :eraminhos, [:animable_class, :animable_id]
12
+ add_index :eraminhos, [:animable_class, :transaction_uuid]
13
+ add_index :eraminhos, [:transaction_uuid]
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: animator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Alec Larsen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '3.0'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '5.0'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '3.0'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '5.0'
53
+ description: Animator is a cleanly namespaced ActiveRecord plugin that hooks into
54
+ the existing model life-cycle allowing you to to restore (Animable#reanimate), query
55
+ (Animable.inanimate), and inspect (Animable#divine) destroyed objects including
56
+ associations without the tedium and ugliness of default scopes, monkey-patched methods,
57
+ and complex callbacks.
58
+ email: aleclarsen42@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - Gemfile
65
+ - LICENSE
66
+ - README.md
67
+ - animator.gemspec
68
+ - lib/animator.rb
69
+ - lib/animator/animable.rb
70
+ - lib/animator/eraminho.rb
71
+ - lib/animator/fey_relation.rb
72
+ - lib/animator/reanimation_error.rb
73
+ - lib/generators/animator/install_generator.rb
74
+ - lib/generators/animator/templates/animator.rb
75
+ - lib/generators/animator/templates/create_eraminhos.rb
76
+ homepage: https://github.com/AlecLarsen/animator
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message: |2+
81
+
82
+ Animator will not work properly until the eraminhos table has been created. You can generate the proper migration by running `rails g animator:install`.
83
+
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.3.6
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.4.5
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Animator is a cleanly namespaced ActiveRecord plugin that hooks into the
103
+ existing model life-cycle allowing you to to restore (Animable#reanimate), query
104
+ (Animable.inanimate), and inspect (Animable#divine) destroyed objects including
105
+ associations without the tedium and ugliness of default scopes, monkey-patched methods,
106
+ and complex callbacks.
107
+ test_files: []