diff --git a/.gitignore b/.gitignore index 9248ddd..da57012 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ pkg .bundle .DS_Store +Gemfile.lock +gemfiles/*.lock diff --git a/.travis.yml b/.travis.yml index 736d1b5..d7c19ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,21 @@ language: ruby +script: "bundle exec rake test" rvm: - - 1.9.2 - 1.9.3 - - jruby-19mode - - rbx-19mode + - 2.0.0 + - 2.1 + - ruby-head + - jruby + - rbx +gemfile: + - gemfiles/active_record_40.gemfile + - gemfiles/active_record_41.gemfile + - gemfiles/active_record_42.gemfile + - gemfiles/active_record_edge.gemfile +matrix: + allow_failures: + - rvm: ruby-head + - rvm: rbx + - rvm: jruby + - gemfile: gemfiles/active_record_edge.gemfile + fast_finish: true diff --git a/Gemfile b/Gemfile index 2f3cc40..a1a1fbf 100644 --- a/Gemfile +++ b/Gemfile @@ -1,20 +1,9 @@ -source "http://rubygems.org" - -gem "activerecord", "~>3.2" +source "https://rubygems.org" # Development dependencies -gem "rake" -gem "activesupport", "~>3.2" - -platforms :ruby do - gem "sqlite3" +group :development do + gem "sqlite3", :platforms => [:ruby] + gem "activerecord-jdbcsqlite3-adapter", :platforms => [:jruby] end -platforms :jruby do - gem "activerecord-jdbcsqlite3-adapter" -end - -group :test do - gem "minitest" - gem "autotest-growl" -end +gemspec diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 36157bd..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,41 +0,0 @@ -GEM - remote: http://rubygems.org/ - specs: - activemodel (3.2.3) - activesupport (= 3.2.3) - builder (~> 3.0.0) - activerecord (3.2.3) - activemodel (= 3.2.3) - activesupport (= 3.2.3) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activerecord-jdbc-adapter (1.2.9.1) - activerecord-jdbcsqlite3-adapter (1.2.9) - activerecord-jdbc-adapter (~> 1.2.9) - jdbc-sqlite3 (~> 3.7.2) - activesupport (3.2.3) - i18n (~> 0.6) - multi_json (~> 1.0) - arel (3.0.2) - autotest-growl (0.2.16) - builder (3.0.0) - i18n (0.6.0) - jdbc-sqlite3 (3.7.2.1) - minitest (2.12.1) - multi_json (1.3.4) - rake (0.9.2.2) - sqlite3 (1.3.6) - tzinfo (0.3.33) - -PLATFORMS - java - ruby - -DEPENDENCIES - activerecord (~> 3.2) - activerecord-jdbcsqlite3-adapter - activesupport (~> 3.2) - autotest-growl - minitest - rake - sqlite3 diff --git a/LICENSE b/LICENSE index e7c30a7..19d12a2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010 Gonçalo Silva +Copyright (c) 2014 Zachary Scott, Gonçalo Silva, Rick Olson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.markdown b/README.md similarity index 80% rename from README.markdown rename to README.md index bf90140..aceb1f1 100755 --- a/README.markdown +++ b/README.md @@ -1,14 +1,16 @@ # ActsAsParanoid -A simple plugin which hides records instead of deleting them, being able to recover them. +[![Build Status](https://travis-ci.org/ActsAsParanoid/acts_as_paranoid.png?branch=master)](https://travis-ci.org/ActsAsParanoid/acts_as_paranoid) -**This branch targets Rails 3.2.** If you're working with another version, switch to the corresponding branch. +A Rails plugin to add soft delete. -## Credits +This gem can be used to hide records instead of deleting them, making them recoverable later. -This plugin was inspired by [acts_as_paranoid](http://github.com/technoweenie/acts_as_paranoid) and [acts_as_active](http://github.com/fernandoluizao/acts_as_active). +## Support -While porting it to Rails 3, I decided to apply the ideas behind those plugins to an unified solution while removing a **lot** of the complexity found in them. I eventually ended up writing a new plugin from scratch. +**This branch targets Rails 4.x.** + +If you're working with another version, switch to the corresponding branch, or require an older version of the acts_as_paranoid gem. ## Usage @@ -187,13 +189,15 @@ Associations are also supported. From the simplest behaviors you'd expect to mor ```ruby class Parent < ActiveRecord::Base - has_many :children, :class_name => "ParanoiacChild" + has_many :children, :class_name => "ParanoiacChild" end class ParanoiacChild < ActiveRecord::Base - belongs_to :parent - belongs_to :parent_including_deleted, :class_name => "Parent", :with_deleted => true - # You cannot name association *_with_deleted + acts_as_paranoid + belongs_to :parent + + # You may need to provide a foreign_key like this + belongs_to :parent_including_deleted, :class_name => "Parent", foreign_key => 'parent_id', :with_deleted => true end parent = Parent.first @@ -214,31 +218,9 @@ Watch out for these caveats: - You cannot name association `*_with_deleted` - `unscoped` will return all records, deleted or not -# Support - -This gem supports the most recent versions of Rails and Ruby. - -## Rails - -For Rails 3.2 check the README at the [rails3.2](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.2) branch and add this to your Gemfile: - - gem "acts_as_paranoid", "~>0.4.0" - -For Rails 3.1 check the README at the [rails3.1](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.1) branch and add this to your Gemfile: - - gem "rails3_acts_as_paranoid", "~>0.1.4" - -For Rails 3.0 check the README at the [rails3.0](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.0) branch and add this to your Gemfile: - - gem "rails3_acts_as_paranoid", "~>0.0.9" - - -## Ruby - -This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode). It *might* work fine in 1.8, but it's not officially supported. - # Acknowledgements +* To [Rick Olson](https://github.com/technoweenie) for creating acts_as_paranoid * To [cheerfulstoic](https://github.com/cheerfulstoic) for adding recursive recovery * To [Jonathan Vaught](https://github.com/gravelpup) for adding paranoid validations * To [Geoffrey Hichborn](https://github.com/phene) for improving the overral code quality and adding support for after_commit @@ -246,5 +228,7 @@ This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode). It *might * To [vikramdhillon](https://github.com/vikramdhillon) for the idea and initial implementation of support for string column type * To [Craig Walker](https://github.com/softcraft-development) for Rails 3.1 support and fixing various pending issues * To [Charles G.](https://github.com/chuckg) for Rails 3.2 support and for making a desperately needed global code refactoring +* To [Gonçalo Silva](https://github.com/goncalossilva) for supporting this gem prior to v0.4.3 +* To [Jean Boussier](https://github.com/byroot) for initial Rails 4.0.0 support -Copyright © 2010 Gonçalo Silva, released under the MIT license +See `LICENSE`. diff --git a/Rakefile b/Rakefile index cd2d548..47167de 100755 --- a/Rakefile +++ b/Rakefile @@ -1,27 +1,34 @@ -begin - require "bundler" - Bundler.setup -rescue LoadError - $stderr.puts "You need to have Bundler installed to be able build this gem." -end +require "bundler/gem_tasks" + require "rake/testtask" -require "rake/rdoctask" +require "rdoc/task" gemspec = eval(File.read(Dir["*.gemspec"].first)) - desc 'Default: run unit tests.' -task :default => :test +task :default => "test:all" + +namespace :test do + %w(active_record_edge active_record_40 active_record_41 active_record_42).each do |version| + desc "Test acts_as_paranoid against #{version}" + task version do + sh "BUNDLE_GEMFILE='gemfiles/#{version}.gemfile' bundle --quiet" + sh "BUNDLE_GEMFILE='gemfiles/#{version}.gemfile' bundle exec rake -t test" + end + end + + desc "Run all tests for acts_as_paranoid" + task :all do + %w(active_record_edge active_record_40 active_record_41 active_record_42).each do |version| + sh "BUNDLE_GEMFILE='gemfiles/#{version}.gemfile' bundle --quiet" + sh "BUNDLE_GEMFILE='gemfiles/#{version}.gemfile' bundle exec rake -t test" + end + end +end -desc 'Test the acts_as_paranoid plugin.' Rake::TestTask.new(:test) do |t| - t.libs << 'lib' t.libs << 'test' - - test_files = FileList['test/**/test_*.rb'] - test_files.exclude('test/test_helper.rb') - t.test_files = test_files - + t.pattern = 'test/test_*.rb' t.verbose = true end @@ -34,18 +41,6 @@ Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_files.include('lib/**/*.rb') end -desc "Validate the gemspec" -task :gemspec do - gemspec.validate -end - -desc "Build gem locally" -task :build => :gemspec do - system "gem build #{gemspec.name}.gemspec" - FileUtils.mkdir_p "pkg" - FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg" -end - desc "Install gem locally" task :install => :build do system "gem install pkg/#{gemspec.name}-#{gemspec.version}" diff --git a/acts_as_paranoid.gemspec b/acts_as_paranoid.gemspec index a6d792a..1a2f5b6 100644 --- a/acts_as_paranoid.gemspec +++ b/acts_as_paranoid.gemspec @@ -1,17 +1,29 @@ -Gem::Specification.new do |s| - s.name = "acts_as_paranoid" - s.version = "0.0.0" - s.platform = Gem::Platform::RUBY - s.authors = ["Goncalo Silva", "Charles G.", "Rick Olson"] - s.email = ["goncalossilva@gmail.com"] - s.homepage = "https://github.com/goncalossilva/rails3_acts_as_paranoid" - s.summary = "Active Record (~>3.2) plugin which allows you to hide and restore records without actually deleting them." - s.description = "Active Record (~>3.2) plugin which allows you to hide and restore records without actually deleting them. Check its GitHub page for more in-depth information." - s.rubyforge_project = s.name +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'acts_as_paranoid/version' - s.required_rubygems_version = ">= 1.3.6" +Gem::Specification.new do |spec| + spec.name = "acts_as_paranoid" + spec.version = ActsAsParanoid::VERSION + spec.authors = ["Zachary Scott", "Goncalo Silva", "Rick Olson"] + spec.email = ["e@zzak.io"] + spec.summary = "Active Record plugin which allows you to hide and restore records without actually deleting them." + spec.description = "Check the home page for more in-depth information." + spec.homepage = "https://github.com/ActsAsParanoid/acts_as_paranoid" + spec.license = "MIT" - s.add_dependency "activerecord", "~> 3.2" + spec.files = Dir["{lib}/**/*.rb", "LICENSE", "*.md"] + spec.test_files = Dir["test/*.rb"] + spec.require_paths = ["lib"] - s.files = Dir["{lib}/**/*.rb", "LICENSE", "*.markdown"] + spec.required_rubygems_version = ">= 1.3.6" + + spec.add_dependency "activerecord", "~> 4.0" + spec.add_dependency "activesupport", "~> 4.0" + + spec.add_development_dependency "bundler", "~> 1.5" + spec.add_development_dependency "rake" + spec.add_development_dependency "rdoc" + spec.add_development_dependency "minitest", ">= 4.0", "<= 6.0" end diff --git a/gemfiles/active_record_40.gemfile b/gemfiles/active_record_40.gemfile new file mode 100644 index 0000000..19c08f5 --- /dev/null +++ b/gemfiles/active_record_40.gemfile @@ -0,0 +1,25 @@ +source 'https://rubygems.org' + +gem 'activerecord', '~> 4.0.0', :require => 'active_record' +gem 'activesupport', '~> 4.0.0', :require => 'active_support' + +platforms :ruby do + if RUBY_VERSION > "2.1.0" + gem 'sqlite3' + else + gem 'sqlite3', '1.3.8' + end +end + +platforms :jruby do + gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0' +end + +platforms :rbx do + gem 'rubysl', '~> 2.0' + gem 'racc' + gem 'rubysl-test-unit' + gem 'rubinius-developer_tools' +end + +gemspec :path => '../' diff --git a/gemfiles/active_record_41.gemfile b/gemfiles/active_record_41.gemfile new file mode 100644 index 0000000..cf062f7 --- /dev/null +++ b/gemfiles/active_record_41.gemfile @@ -0,0 +1,25 @@ +source 'https://rubygems.org' + +gem 'activerecord', '~> 4.1.0', :require => 'active_record' +gem 'activesupport', '~> 4.1.0', :require => 'active_support' + +platforms :ruby do + if RUBY_VERSION > "2.1.0" + gem 'sqlite3' + else + gem 'sqlite3', '1.3.8' + end +end + +platforms :jruby do + gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0' +end + +platforms :rbx do + gem 'rubysl', '~> 2.0' + gem 'racc' + gem 'minitest' + gem 'rubinius-developer_tools' +end + +gemspec :path => '../' diff --git a/gemfiles/active_record_42.gemfile b/gemfiles/active_record_42.gemfile new file mode 100644 index 0000000..30ece1b --- /dev/null +++ b/gemfiles/active_record_42.gemfile @@ -0,0 +1,25 @@ +source 'https://rubygems.org' + +gem 'activerecord', '~> 4.2.0.beta1', :require => 'active_record' +gem 'activesupport', '~> 4.2.0.beta1', :require => 'active_support' + +platforms :ruby do + if RUBY_VERSION > "2.1.0" + gem 'sqlite3' + else + gem 'sqlite3', '1.3.8' + end +end + +platforms :jruby do + gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0' +end + +platforms :rbx do + gem 'rubysl', '~> 2.0' + gem 'racc' + gem 'minitest' + gem 'rubinius-developer_tools' +end + +gemspec :path => '../' diff --git a/gemfiles/active_record_edge.gemfile b/gemfiles/active_record_edge.gemfile new file mode 100644 index 0000000..360778a --- /dev/null +++ b/gemfiles/active_record_edge.gemfile @@ -0,0 +1,29 @@ +source 'https://rubygems.org' + +git 'git://github.com/rails/rails.git' do + gem 'activerecord', :require => 'active_record' + gem 'activesupport', :require => 'active_support' +end + +gem 'arel', :github => 'rails/arel' + +platforms :ruby do + if RUBY_VERSION > "2.1.0" + gem 'sqlite3' + else + gem 'sqlite3', '1.3.8' + end +end + +platforms :jruby do + gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0' +end + +platforms :rbx do + gem 'rubysl', '~> 2.0' + gem 'racc' + gem 'minitest' + gem 'rubinius-developer_tools' +end + +gemspec :path => '../' diff --git a/init.rb b/init.rb deleted file mode 100755 index d0833ab..0000000 --- a/init.rb +++ /dev/null @@ -1 +0,0 @@ -require 'acts_as_paranoid' diff --git a/lib/acts_as_paranoid.rb b/lib/acts_as_paranoid.rb index e766c06..0a9a49b 100644 --- a/lib/acts_as_paranoid.rb +++ b/lib/acts_as_paranoid.rb @@ -1,39 +1,35 @@ -require 'active_record/base' -require 'active_record/relation' -require 'active_record/callbacks' require 'acts_as_paranoid/core' require 'acts_as_paranoid/associations' require 'acts_as_paranoid/validations' require 'acts_as_paranoid/relation' - module ActsAsParanoid - + def paranoid? self.included_modules.include?(ActsAsParanoid::Core) end - + def validates_as_paranoid include ActsAsParanoid::Validations end - + def acts_as_paranoid(options = {}) raise ArgumentError, "Hash expected, got #{options.class.name}" if not options.is_a?(Hash) and not options.empty? - + class_attribute :paranoid_configuration, :paranoid_column_reference - - self.paranoid_configuration = { :column => "deleted_at", :column_type => "time", :recover_dependent_associations => true, :dependent_recovery_window => 2.minutes } + + self.paranoid_configuration = { :column => "deleted_at", :column_type => "time", :recover_dependent_associations => true, :dependent_recovery_window => 2.minutes, :dependent_destroy_paranoid_only => false } self.paranoid_configuration.merge!({ :deleted_value => "deleted" }) if options[:column_type] == "string" self.paranoid_configuration.merge!(options) # user options raise ArgumentError, "'time', 'boolean' or 'string' expected for :column_type option, got #{paranoid_configuration[:column_type]}" unless ['time', 'boolean', 'string'].include? paranoid_configuration[:column_type] self.paranoid_column_reference = "#{self.table_name}.#{paranoid_configuration[:column]}" - + return if paranoid? - + include ActsAsParanoid::Core - + # Magic! default_scope { where(paranoid_default_scope_sql) } diff --git a/lib/acts_as_paranoid/associations.rb b/lib/acts_as_paranoid/associations.rb index bbf6fe4..aa5a563 100644 --- a/lib/acts_as_paranoid/associations.rb +++ b/lib/acts_as_paranoid/associations.rb @@ -8,12 +8,17 @@ class << base end module ClassMethods - def belongs_to_with_deleted(target, options = {}) - with_deleted = options.delete(:with_deleted) - result = belongs_to_without_deleted(target, options) + def belongs_to_with_deleted(target, scope = nil, options = {}) + with_deleted = (scope.is_a?(Hash) ? scope : options).delete(:with_deleted) + result = belongs_to_without_deleted(target, scope, options) if with_deleted - result.options[:with_deleted] = with_deleted + if result.is_a? Hash + result.values.last.options[:with_deleted] = with_deleted + else + result.options[:with_deleted] = with_deleted + end + unless method_defined? "#{target}_with_unscoped" class_eval <<-RUBY, __FILE__, __LINE__ def #{target}_with_unscoped(*args) diff --git a/lib/acts_as_paranoid/core.rb b/lib/acts_as_paranoid/core.rb index c081abc..3525ce8 100644 --- a/lib/acts_as_paranoid/core.rb +++ b/lib/acts_as_paranoid/core.rb @@ -6,7 +6,7 @@ def self.included(base) module ClassMethods def self.extended(base) - base.define_callbacks :recover + base.define_callbacks :recover, terminator: lambda { |target, result| result == false } end def before_recover(method) @@ -34,16 +34,16 @@ def delete_all!(conditions = nil) end def delete_all(conditions = nil) - update_all ["#{paranoid_configuration[:column]} = ?", delete_now_value], conditions + where(conditions).update_all(["#{paranoid_configuration[:column]} = ?", delete_now_value]) end def paranoid_default_scope_sql if string_type_with_deleted_value? - self.scoped.table[paranoid_column].eq(nil). - or(self.scoped.table[paranoid_column].not_eq(paranoid_configuration[:deleted_value])). - to_sql + self.all.table[paranoid_column].eq(nil). + or(self.all.table[paranoid_column].not_eq(paranoid_configuration[:deleted_value])). + to_sql else - self.scoped.table[paranoid_column].eq(nil).to_sql + self.all.table[paranoid_column].eq(nil).to_sql end end @@ -60,22 +60,31 @@ def paranoid_column_type end def dependent_associations - self.reflect_on_all_associations.select {|a| [:destroy, :delete_all].include?(a.options[:dependent]) } + self.reflect_on_all_associations.select { |a| [:destroy, :delete_all].include?(a.options[:dependent]) } end def delete_now_value case paranoid_configuration[:column_type] - when "time" then Time.now - when "boolean" then true - when "string" then paranoid_configuration[:deleted_value] + when "time" + Time.now + when "boolean" + true + when "string" + paranoid_configuration[:deleted_value] end end - protected + protected def without_paranoid_default_scope - scope = self.scoped.with_default_scope - scope.where_values.delete(paranoid_default_scope_sql) + scope = self.all + if scope.where_values.include? paranoid_default_scope_sql + # ActiveRecord 4.1 + scope.where_values.delete(paranoid_default_scope_sql) + else + scope = scope.with_default_scope + scope.where_values.delete(paranoid_default_scope_sql) + end scope end @@ -89,10 +98,10 @@ def paranoid_value self.send(self.class.paranoid_column) end - def destroy! + def destroy_fully! with_transaction_returning_status do + destroy_dependent_associations! run_callbacks :destroy do - destroy_dependent_associations! # Handle composite keys, otherwise we would just use `self.class.primary_key.to_sym => self.id`. self.class.delete_all!(Hash[[Array(self.class.primary_key), Array(self.id)].transpose]) if persisted? self.paranoid_value = self.class.delete_now_value @@ -101,38 +110,49 @@ def destroy! end end - def destroy - if !deleted? + def destroy! + unless deleted? with_transaction_returning_status do - run_callbacks :destroy do - # Handle composite keys, otherwise we would just use `self.class.primary_key.to_sym => self.id`. - self.class.delete_all(Hash[[Array(self.class.primary_key), Array(self.id)].transpose]) if persisted? + if self.class.paranoid_configuration[:dependent_destroy_paranoid_only] + destroy_paranoid_associations self.paranoid_value = self.class.delete_now_value - self + self.save! + else + run_callbacks :destroy do + # Handle composite keys, otherwise we would just use `self.class.primary_key.to_sym => self.id`. + self.class.delete_all(Hash[[Array(self.class.primary_key), Array(self.id)].transpose]) if persisted? + self.paranoid_value = self.class.delete_now_value + self + end end end else - destroy! + destroy_fully! end end + def destroy + destroy! + end + def recover(options={}) options = { - :recursive => self.class.paranoid_configuration[:recover_dependent_associations], - :recovery_window => self.class.paranoid_configuration[:dependent_recovery_window] + :recursive => self.class.paranoid_configuration[:recover_dependent_associations], + :recovery_window => self.class.paranoid_configuration[:dependent_recovery_window] }.merge(options) self.class.transaction do run_callbacks :recover do - recover_dependent_associations(options[:recovery_window], options) if options[:recursive] - + paranoid_original_value = self.paranoid_value self.paranoid_value = nil - self.save + self.save! + + recover_dependent_associations(paranoid_original_value, options[:recovery_window], options) if options[:recursive] end end end - - def recover_dependent_associations(window, options) + + def recover_dependent_associations(paranoid_original_value, window, options) self.class.dependent_associations.each do |reflection| next unless (klass = get_reflection_class(reflection)).paranoid? @@ -144,11 +164,15 @@ def recover_dependent_associations(window, options) # We can only recover by window if both parent and dependant have a # paranoid column type of :time. if self.class.paranoid_column_type == :time && klass.paranoid_column_type == :time - scope = scope.merge(klass.deleted_inside_time_window(paranoid_value, window)) + scope = scope.deleted_inside_time_window(paranoid_original_value, window) end - scope.each do |object| - object.recover(options) + unless reflection.options[:dependent] == :delete_all + scope.each do |object| + object.recover(options) + end + else + scope.update_all(self.class.paranoid_column => nil) end end end @@ -157,26 +181,40 @@ def destroy_dependent_associations! self.class.dependent_associations.each do |reflection| next unless (klass = get_reflection_class(reflection)).paranoid? - scope = klass.only_deleted - # Merge in the association's scope - scope = scope.merge(association(reflection.name).association_scope) + scope = association(reflection.name).association_scope scope.each do |object| - object.destroy! + object.destroy_fully! + end + end + end + + def destroy_paranoid_associations + self.class.dependent_associations.each do |reflection| + if reflection.klass.paranoid? + dependent_type = reflection.options[:dependent] + association_scope = association(reflection.name).association_scope + if dependent_type == :destroy + association_scope.each do |object| + object.send(reflection.options[:dependent]) + end + elsif dependent_type == :delete_all + association_scope.delete_all + end end end end def deleted? !(paranoid_value.nil? || - (self.class.string_type_with_deleted_value? && paranoid_value != self.class.delete_now_value)) + (self.class.string_type_with_deleted_value? && paranoid_value != self.class.delete_now_value)) end alias_method :destroyed?, :deleted? private - + def get_reflection_class(reflection) if reflection.macro == :belongs_to && reflection.options.include?(:polymorphic) self.send(reflection.foreign_type).constantize diff --git a/lib/acts_as_paranoid/relation.rb b/lib/acts_as_paranoid/relation.rb index 6ae97ff..1a4397c 100644 --- a/lib/acts_as_paranoid/relation.rb +++ b/lib/acts_as_paranoid/relation.rb @@ -5,7 +5,7 @@ def self.included(base) def paranoid? klass.try(:paranoid?) ? true : false end - + def paranoid_deletion_attributes { klass.paranoid_column => klass.delete_now_value } end @@ -18,10 +18,10 @@ def delete_all!(conditions = nil) orig_delete_all end end - + def delete_all(conditions = nil) if paranoid? - update_all(paranoid_deletion_attributes, conditions) + where(conditions).update_all(paranoid_deletion_attributes) else delete_all!(conditions) end diff --git a/lib/acts_as_paranoid/validations.rb b/lib/acts_as_paranoid/validations.rb index 5db78df..d0dc80b 100644 --- a/lib/acts_as_paranoid/validations.rb +++ b/lib/acts_as_paranoid/validations.rb @@ -11,10 +11,15 @@ def validate_each(record, attribute, value) finder_class = find_finder_class_for(record) table = finder_class.arel_table - coder = record.class.serialized_attributes[attribute.to_s] + # TODO: Use record.class.column_types[attribute.to_s].coder ? + coder = record.class.column_types[attribute.to_s] if value && coder - value = coder.dump value + value = if coder.respond_to? :type_cast_for_database + coder.type_cast_for_database value + else + coder.type_cast_for_write value + end end relation = build_relation(finder_class, table, attribute, value) diff --git a/lib/acts_as_paranoid/version.rb b/lib/acts_as_paranoid/version.rb new file mode 100644 index 0000000..00fc7c2 --- /dev/null +++ b/lib/acts_as_paranoid/version.rb @@ -0,0 +1,3 @@ +module ActsAsParanoid + VERSION = "0.5.0.beta1" +end diff --git a/test/test_associations.rb b/test/test_associations.rb index 7fb1381..55b0a79 100644 --- a/test/test_associations.rb +++ b/test/test_associations.rb @@ -2,8 +2,6 @@ class AssociationsTest < ParanoidBaseTest def test_removal_with_associations - # This test shows that the current implementation doesn't handle - # assciation deletion correctly (when hard deleting via parent-object) paranoid_company_1 = ParanoidDestroyCompany.create! :name => "ParanoidDestroyCompany #1" paranoid_company_2 = ParanoidDeleteCompany.create! :name => "ParanoidDestroyCompany #1" paranoid_company_1.paranoid_products.create! :name => "ParanoidProduct #1" @@ -19,21 +17,34 @@ def test_removal_with_associations assert_equal 1, ParanoidDestroyCompany.with_deleted.count assert_equal 2, ParanoidProduct.with_deleted.count - ParanoidDestroyCompany.with_deleted.first.destroy! + ParanoidDestroyCompany.with_deleted.first.destroy assert_equal 0, ParanoidDestroyCompany.count assert_equal 1, ParanoidProduct.count assert_equal 0, ParanoidDestroyCompany.with_deleted.count assert_equal 1, ParanoidProduct.with_deleted.count - ParanoidDeleteCompany.with_deleted.first.destroy! + ParanoidDeleteCompany.first.destroy + assert_equal 0, ParanoidDeleteCompany.count + assert_equal 0, ParanoidProduct.count + assert_equal 1, ParanoidDeleteCompany.with_deleted.count + assert_equal 1, ParanoidProduct.with_deleted.count + + ParanoidDeleteCompany.with_deleted.first.destroy assert_equal 0, ParanoidDeleteCompany.count assert_equal 0, ParanoidProduct.count assert_equal 0, ParanoidDeleteCompany.with_deleted.count assert_equal 0, ParanoidProduct.with_deleted.count end + def test_belongs_to_with_scope_option + paranoid_has_many_dependant = ParanoidHasManyDependant.new + includes_values = ParanoidTime.includes(:not_paranoid).includes_values + + assert_equal includes_values, paranoid_has_many_dependant.association(:paranoid_time_with_scope).scope.includes_values + end + def test_belongs_to_with_deleted - paranoid_time = ParanoidTime.first + paranoid_time = ParanoidTime.first paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants.create(:name => 'dependant!') assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time @@ -46,7 +57,7 @@ def test_belongs_to_with_deleted end def test_belongs_to_polymorphic_with_deleted - paranoid_time = ParanoidTime.first + paranoid_time = ParanoidTime.first paranoid_has_many_dependant = ParanoidHasManyDependant.create!(:name => 'dependant!', :paranoid_time_polymorphic_with_deleted => paranoid_time) assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time @@ -72,19 +83,19 @@ def test_belongs_to_nil_polymorphic_with_deleted end def test_belongs_to_options - paranoid_time = ParanoidHasManyDependant.reflections[:paranoid_time] + paranoid_time = ParanoidHasManyDependant.reflections.with_indifferent_access[:paranoid_time] assert_equal :belongs_to, paranoid_time.macro assert_nil paranoid_time.options[:with_deleted] end def test_belongs_to_with_deleted_options - paranoid_time_with_deleted = ParanoidHasManyDependant.reflections[:paranoid_time_with_deleted] + paranoid_time_with_deleted = ParanoidHasManyDependant.reflections.with_indifferent_access[:paranoid_time_with_deleted] assert_equal :belongs_to, paranoid_time_with_deleted.macro assert paranoid_time_with_deleted.options[:with_deleted] end def test_belongs_to_polymorphic_with_deleted_options - paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections[:paranoid_time_polymorphic_with_deleted] + paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections.with_indifferent_access[:paranoid_time_polymorphic_with_deleted] assert_equal :belongs_to, paranoid_time_polymorphic_with_deleted.macro assert paranoid_time_polymorphic_with_deleted.options[:with_deleted] end @@ -101,6 +112,9 @@ def test_only_find_associated_records_when_finding_with_paranoid_deleted child.destroy assert_paranoid_deletion(child) + parent.reload + + assert_equal [], parent.paranoid_has_many_dependants.to_a assert_equal [child], parent.paranoid_has_many_dependants.with_deleted.to_a end diff --git a/test/test_core.rb b/test/test_core.rb index e5b7dd6..cc189b5 100644 --- a/test/test_core.rb +++ b/test/test_core.rb @@ -4,9 +4,8 @@ class ParanoidTest < ParanoidBaseTest def test_paranoid? assert !NotParanoid.paranoid? assert_raise(NoMethodError) { NotParanoid.delete_all! } - assert_raise(NoMethodError) { NotParanoid.first.destroy! } assert_raise(NoMethodError) { NotParanoid.with_deleted } - assert_raise(NoMethodError) { NotParanoid.only_deleted } + assert_raise(NoMethodError) { NotParanoid.only_deleted } assert ParanoidTime.paranoid? end @@ -32,7 +31,7 @@ def test_fake_removal assert_equal 2, ParanoidTime.count assert_equal 1, ParanoidBoolean.count assert_equal 0, ParanoidString.count - assert_equal 1, ParanoidTime.only_deleted.count + assert_equal 1, ParanoidTime.only_deleted.count assert_equal 2, ParanoidBoolean.only_deleted.count assert_equal 1, ParanoidString.only_deleted.count assert_equal 3, ParanoidTime.with_deleted.count @@ -41,9 +40,9 @@ def test_fake_removal end def test_real_removal - ParanoidTime.first.destroy! + ParanoidTime.first.destroy_fully! ParanoidBoolean.delete_all!("name = 'extremely paranoid' OR name = 'really paranoid'") - ParanoidString.first.destroy! + ParanoidString.first.destroy_fully! assert_equal 2, ParanoidTime.count assert_equal 1, ParanoidBoolean.count assert_equal 0, ParanoidString.count @@ -60,7 +59,7 @@ def test_real_removal ParanoidTime.delete_all! assert_empty ParanoidTime.all - assert_empty ParanoidTime.with_deleted.all + assert_empty ParanoidTime.with_deleted end def test_non_persisted_destroy @@ -77,6 +76,10 @@ def test_non_persisted_destroy! assert_not_nil pt.paranoid_value end + def test_removal_not_persisted + assert ParanoidTime.new.destroy + end + def test_recovery assert_equal 3, ParanoidBoolean.count ParanoidBoolean.first.destroy @@ -93,7 +96,7 @@ def test_recovery def setup_recursive_tests @paranoid_time_object = ParanoidTime.first - + # Create one extra ParanoidHasManyDependant record so that we can validate # the correct dependants are recovered. ParanoidTime.where('id <> ?', @paranoid_time_object.id).first.paranoid_has_many_dependants.create(:name => "should not be recovered").destroy @@ -141,12 +144,18 @@ def test_recursive_fake_removal assert_equal 0, ParanoidHasOneDependant.count assert_equal 1, NotParanoid.count assert_equal 0, HasOneNotParanoid.count + + assert_equal 3, ParanoidTime.with_deleted.count + assert_equal 4, ParanoidHasManyDependant.with_deleted.count + assert_equal 3, ParanoidBelongsDependant.with_deleted.count + assert_equal @paranoid_boolean_count + 3, ParanoidBoolean.with_deleted.count + assert_equal 3, ParanoidHasOneDependant.with_deleted.count end def test_recursive_real_removal - setup_recursive_tests + setup_recursive_tests - @paranoid_time_object.destroy! + @paranoid_time_object.destroy_fully! assert_equal 0, ParanoidTime.only_deleted.count assert_equal 1, ParanoidHasManyDependant.only_deleted.count @@ -180,8 +189,8 @@ def test_recursive_recovery_dependant_window @paranoid_time_object.destroy @paranoid_time_object.reload - # Stop the following from recovering: - # - ParanoidHasManyDependant and its ParanoidBelongsDependant + # Stop the following from recovering: + # - ParanoidHasManyDependant and its ParanoidBelongsDependant # - A single ParanoidBelongsDependant, but not its parent dependants = @paranoid_time_object.paranoid_has_many_dependants.with_deleted dependants.first.update_attribute(:deleted_at, 2.days.ago) @@ -197,38 +206,38 @@ def test_recursive_recovery_dependant_window assert_equal 1, NotParanoid.count assert_equal 0, HasOneNotParanoid.count end - + def test_recursive_recovery_for_belongs_to_polymorphic child_1 = ParanoidAndroid.create section_1 = ParanoidSection.create(:paranoid_thing => child_1) - + child_2 = ParanoidHuman.create(:gender => 'male') section_2 = ParanoidSection.create(:paranoid_thing => child_2) - + assert_equal section_1.paranoid_thing, child_1 assert_equal section_1.paranoid_thing.class, ParanoidAndroid assert_equal section_2.paranoid_thing, child_2 assert_equal section_2.paranoid_thing.class, ParanoidHuman - + parent = ParanoidTime.create(:name => "paranoid_parent") parent.paranoid_sections << section_1 parent.paranoid_sections << section_2 - + assert_equal 4, ParanoidTime.count assert_equal 2, ParanoidSection.count assert_equal 1, ParanoidAndroid.count assert_equal 1, ParanoidHuman.count - + parent.destroy - + assert_equal 3, ParanoidTime.count assert_equal 0, ParanoidSection.count assert_equal 0, ParanoidAndroid.count assert_equal 0, ParanoidHuman.count - + parent.reload parent.recover - + assert_equal 4, ParanoidTime.count assert_equal 2, ParanoidSection.count assert_equal 1, ParanoidAndroid.count @@ -259,25 +268,25 @@ def test_deleted? ParanoidString.first.destroy assert ParanoidString.with_deleted.first.deleted? end - - def test_paranoid_destroy_callbacks + + def test_paranoid_destroy_callbacks @paranoid_with_callback = ParanoidWithCallback.first ParanoidWithCallback.transaction do @paranoid_with_callback.destroy end - + assert @paranoid_with_callback.called_before_destroy assert @paranoid_with_callback.called_after_destroy assert @paranoid_with_callback.called_after_commit_on_destroy end - + def test_hard_destroy_callbacks @paranoid_with_callback = ParanoidWithCallback.first - + ParanoidWithCallback.transaction do @paranoid_with_callback.destroy! end - + assert @paranoid_with_callback.called_before_destroy assert @paranoid_with_callback.called_after_destroy assert @paranoid_with_callback.called_after_commit_on_destroy @@ -296,52 +305,52 @@ def test_recovery_callbacks end assert @paranoid_with_callback.called_before_recover - assert @paranoid_with_callback.called_after_recover + assert @paranoid_with_callback.called_after_recover end def test_delete_by_multiple_id_is_paranoid model_a = ParanoidBelongsDependant.create model_b = ParanoidBelongsDependant.create ParanoidBelongsDependant.delete([model_a.id, model_b.id]) - + assert_paranoid_deletion(model_a) assert_paranoid_deletion(model_b) end - + def test_destroy_by_multiple_id_is_paranoid model_a = ParanoidBelongsDependant.create model_b = ParanoidBelongsDependant.create ParanoidBelongsDependant.destroy([model_a.id, model_b.id]) - + assert_paranoid_deletion(model_a) assert_paranoid_deletion(model_b) end - + def test_delete_by_single_id_is_paranoid model = ParanoidBelongsDependant.create ParanoidBelongsDependant.delete(model.id) - + assert_paranoid_deletion(model) end - + def test_destroy_by_single_id_is_paranoid model = ParanoidBelongsDependant.create ParanoidBelongsDependant.destroy(model.id) - + assert_paranoid_deletion(model) end - + def test_instance_delete_is_paranoid model = ParanoidBelongsDependant.create model.delete - + assert_paranoid_deletion(model) end - + def test_instance_destroy_is_paranoid model = ParanoidBelongsDependant.create model.destroy - + assert_paranoid_deletion(model) end diff --git a/test/test_default_scopes.rb b/test/test_default_scopes.rb index f0344de..330ad93 100644 --- a/test/test_default_scopes.rb +++ b/test/test_default_scopes.rb @@ -27,7 +27,7 @@ def test_fake_removal_with_multiple_default_scope assert_equal 3, ParanoidHuman.with_deleted.count assert_equal 4, ParanoidHuman.unscoped.count end - + def test_real_removal_with_multiple_default_scope # two-step ParanoidHuman.first.destroy @@ -37,7 +37,7 @@ def test_real_removal_with_multiple_default_scope assert_equal 0, ParanoidHuman.only_deleted.count assert_equal 3, ParanoidHuman.unscoped.count - ParanoidHuman.first.destroy! + ParanoidHuman.first.destroy_fully! assert_equal 1, ParanoidHuman.count assert_equal 1, ParanoidHuman.with_deleted.count assert_equal 0, ParanoidHuman.only_deleted.count diff --git a/test/test_helper.rb b/test/test_helper.rb index 330ed78..7f968ab 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,16 +1,20 @@ -require 'rubygems' -require 'test/unit' -require 'active_support' -require 'active_record' -require 'active_model' +require 'bundler' +begin + Bundler.require(:default, :development) +rescue Bundler::BundlerError => e + $stderr.puts e.message + $stderr.puts "Run `bundle install` to install missing gems" + exit e.status_code +end -$:.unshift "#{File.dirname(__FILE__)}/../" -$:.unshift "#{File.dirname(__FILE__)}/../lib/" -$:.unshift "#{File.dirname(__FILE__)}/../lib/validations" +require 'acts_as_paranoid' +require 'minitest/autorun' -require 'init' +# Silence deprecation halfway through the test +I18n.enforce_available_locales = true ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") +ActiveRecord::Schema.verbose = false def setup_db ActiveRecord::Schema.define(:version => 1) do @@ -20,7 +24,7 @@ def setup_db t.integer :paranoid_belongs_dependant_id t.integer :not_paranoid_id - t.timestamps + timestamps t end create_table :paranoid_booleans do |t| @@ -28,7 +32,7 @@ def setup_db t.boolean :is_deleted t.integer :paranoid_time_id - t.timestamps + timestamps t end create_table :paranoid_strings do |t| @@ -40,14 +44,14 @@ def setup_db t.string :name t.integer :paranoid_time_id - t.timestamps + timestamps t end create_table :has_one_not_paranoids do |t| t.string :name t.integer :paranoid_time_id - t.timestamps + timestamps t end create_table :paranoid_has_many_dependants do |t| @@ -57,14 +61,14 @@ def setup_db t.string :paranoid_time_polymorphic_with_deleted_type t.integer :paranoid_belongs_dependant_id - t.timestamps + timestamps t end create_table :paranoid_belongs_dependants do |t| t.string :name t.datetime :deleted_at - t.timestamps + timestamps t end create_table :paranoid_has_one_dependants do |t| @@ -72,105 +76,105 @@ def setup_db t.datetime :deleted_at t.integer :paranoid_boolean_id - t.timestamps + timestamps t end - + create_table :paranoid_with_callbacks do |t| t.string :name t.datetime :deleted_at - - t.timestamps + + timestamps t end create_table :paranoid_destroy_companies do |t| t.string :name t.datetime :deleted_at - - t.timestamps + + timestamps t end - + create_table :paranoid_delete_companies do |t| t.string :name t.datetime :deleted_at - - t.timestamps + + timestamps t end - + create_table :paranoid_products do |t| t.integer :paranoid_destroy_company_id t.integer :paranoid_delete_company_id t.string :name t.datetime :deleted_at - - t.timestamps + + timestamps t end - + create_table :super_paranoids do |t| t.string :type t.references :has_many_inherited_super_paranoidz t.datetime :deleted_at - - t.timestamps + + timestamps t end - + create_table :has_many_inherited_super_paranoidzs do |t| t.references :super_paranoidz t.datetime :deleted_at - - t.timestamps + + timestamps t end - + create_table :paranoid_many_many_parent_lefts do |t| t.string :name - t.timestamps + timestamps t end create_table :paranoid_many_many_parent_rights do |t| t.string :name - t.timestamps + timestamps t end - + create_table :paranoid_many_many_children do |t| t.integer :paranoid_many_many_parent_left_id t.integer :paranoid_many_many_parent_right_id t.datetime :deleted_at - t.timestamps + timestamps t end - + create_table :paranoid_with_scoped_validations do |t| t.string :name t.string :category t.datetime :deleted_at - t.timestamps + timestamps t end create_table :paranoid_forests do |t| t.string :name t.boolean :rainforest t.datetime :deleted_at - - t.timestamps + + timestamps t end - + create_table :paranoid_trees do |t| t.integer :paranoid_forest_id t.string :name t.datetime :deleted_at - - t.timestamps + + timestamps t end create_table :paranoid_humen do |t| t.string :gender t.datetime :deleted_at - t.timestamps + timestamps t end - + create_table :paranoid_androids do |t| t.datetime :deleted_at end - + create_table :paranoid_sections do |t| t.integer :paranoid_time_id t.integer :paranoid_thing_id @@ -180,6 +184,11 @@ def setup_db end end +def timestamps(table) + table.column :created_at , :timestamp, :null => false + table.column :updated_at , :timestamp, :null => false +end + def teardown_db ActiveRecord::Base.connection.tables.each do |table| ActiveRecord::Base.connection.drop_table(table) @@ -229,6 +238,7 @@ class DoubleHasOneNotParanoid < HasOneNotParanoid class ParanoidHasManyDependant < ActiveRecord::Base acts_as_paranoid belongs_to :paranoid_time + belongs_to :paranoid_time_with_scope, -> { includes(:not_paranoid) }, :class_name => 'ParanoidTime', :foreign_key => :paranoid_time_id belongs_to :paranoid_time_with_deleted, :class_name => 'ParanoidTime', :foreign_key => :paranoid_time_id, :with_deleted => true belongs_to :paranoid_time_polymorphic_with_deleted, :class_name => 'ParanoidTime', :foreign_key => :paranoid_time_id, :polymorphic => true, :with_deleted => true @@ -249,31 +259,31 @@ class ParanoidHasOneDependant < ActiveRecord::Base class ParanoidWithCallback < ActiveRecord::Base acts_as_paranoid - + attr_accessor :called_before_destroy, :called_after_destroy, :called_after_commit_on_destroy attr_accessor :called_before_recover, :called_after_recover - + before_destroy :call_me_before_destroy after_destroy :call_me_after_destroy - + after_commit :call_me_after_commit_on_destroy, :on => :destroy before_recover :call_me_before_recover after_recover :call_me_after_recover - + def initialize(*attrs) @called_before_destroy = @called_after_destroy = @called_after_commit_on_destroy = false super(*attrs) end - + def call_me_before_destroy @called_before_destroy = true end - + def call_me_after_destroy @called_after_destroy = true end - + def call_me_after_commit_on_destroy @called_after_commit_on_destroy = true end @@ -319,25 +329,6 @@ class InheritedParanoid < SuperParanoid acts_as_paranoid end -class ParanoidObserver < ActiveRecord::Observer - observe :paranoid_with_callback - - attr_accessor :called_before_recover, :called_after_recover - - def before_recover(paranoid_object) - self.called_before_recover = paranoid_object - end - - def after_recover(paranoid_object) - self.called_after_recover = paranoid_object - end - - def reset - self.called_before_recover = nil - self.called_after_recover = nil - end -end - class ParanoidManyManyParentLeft < ActiveRecord::Base has_many :paranoid_many_many_children @@ -360,8 +351,6 @@ class ParanoidWithScopedValidation < ActiveRecord::Base validates_uniqueness_of :name, :scope => :category end -ParanoidWithCallback.add_observer(ParanoidObserver.instance) - class ParanoidBaseTest < ActiveSupport::TestCase def setup setup_db @@ -374,24 +363,22 @@ def setup ParanoidString.create! :name => "strings can be paranoid" NotParanoid.create! :name => "no paranoid goals" ParanoidWithCallback.create! :name => "paranoid with callbacks" - - ParanoidObserver.instance.reset end def teardown teardown_db end - + def assert_empty(collection) assert(collection.respond_to?(:empty?) && collection.empty?) end - + def assert_paranoid_deletion(model) row = find_row(model) assert_not_nil row, "#{model.class} entirely deleted" assert_not_nil row["deleted_at"], "Deleted at not set" end - + def assert_non_paranoid_deletion(model) row = find_row(model) assert_nil row, "#{model.class} still exists" @@ -407,11 +394,9 @@ def find_row(model) class ParanoidForest < ActiveRecord::Base acts_as_paranoid - # HACK: scope throws an error on 1.8.7 because the logger isn't initialized (see https://github.com/Casecommons/pg_search/issues/26) - require "active_support/core_ext/logger.rb" ActiveRecord::Base.logger = Logger.new(StringIO.new) - scope :rainforest, where(:rainforest => true) + scope :rainforest, lambda{ where(:rainforest => true) } has_many :paranoid_trees, :dependent => :destroy end @@ -424,7 +409,7 @@ class ParanoidTree < ActiveRecord::Base class ParanoidHuman < ActiveRecord::Base acts_as_paranoid - default_scope where('gender = ?', 'male') + default_scope { where('gender = ?', 'male') } end class ParanoidAndroid < ActiveRecord::Base diff --git a/test/test_inheritance.rb b/test/test_inheritance.rb index bad4dc0..d4a3f57 100644 --- a/test/test_inheritance.rb +++ b/test/test_inheritance.rb @@ -7,9 +7,8 @@ def test_destroy_dependents_with_inheritance has_many_inherited_super_paranoidz.super_paranoidz.create assert_nothing_raised(NoMethodError) { has_many_inherited_super_paranoidz.destroy } end - + def test_class_instance_variables_are_inherited assert_nothing_raised(ActiveRecord::StatementInvalid) { InheritedParanoid.paranoid_column } end end - diff --git a/test/test_observers.rb b/test/test_observers.rb deleted file mode 100644 index f67b3fb..0000000 --- a/test/test_observers.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'test_helper' - -class ParanoidObserverTest < ParanoidBaseTest - def test_called_observer_methods - @subject = ParanoidWithCallback.new - @subject.save - - assert_nil ParanoidObserver.instance.called_before_recover - assert_nil ParanoidObserver.instance.called_after_recover - - ParanoidWithCallback.find(@subject.id).recover - - assert_equal @subject, ParanoidObserver.instance.called_before_recover - assert_equal @subject, ParanoidObserver.instance.called_after_recover - end -end diff --git a/test/test_relations.rb b/test/test_relations.rb index db28164..bef6595 100644 --- a/test/test_relations.rb +++ b/test/test_relations.rb @@ -2,7 +2,7 @@ class RelationsTest < ParanoidBaseTest def setup - setup_db + setup_db @paranoid_forest_1 = ParanoidForest.create! :name => "ParanoidForest #1" @paranoid_forest_2 = ParanoidForest.create! :name => "ParanoidForest #2", :rainforest => true @@ -72,10 +72,10 @@ def test_associations_filtered_by_only_deleted assert_equal 2, @paranoid_forest_1.paranoid_trees.only_deleted.count assert_equal 3, ParanoidTree.only_deleted.count end - + def test_fake_removal_through_relation # destroy: through a relation. - ParanoidForest.rainforest.destroy(@paranoid_forest_3) + ParanoidForest.rainforest.destroy(@paranoid_forest_3.id) assert_equal 1, ParanoidForest.rainforest.count assert_equal 2, ParanoidForest.rainforest.with_deleted.count assert_equal 1, ParanoidForest.rainforest.only_deleted.count @@ -85,18 +85,18 @@ def test_fake_removal_through_relation assert_equal 0, @paranoid_forest_2.paranoid_trees(true).count assert_equal 2, @paranoid_forest_2.paranoid_trees(true).with_deleted.count end - + def test_real_removal_through_relation # destroy!: aliased to delete ParanoidForest.rainforest.destroy!(@paranoid_forest_3) assert_equal 1, ParanoidForest.rainforest.count assert_equal 1, ParanoidForest.rainforest.with_deleted.count assert_equal 0, ParanoidForest.rainforest.only_deleted.count - + # destroy: two-step through a relation paranoid_tree = @paranoid_forest_1.paranoid_trees.first - @paranoid_forest_1.paranoid_trees.order(:id).destroy(paranoid_tree) - @paranoid_forest_1.paranoid_trees.only_deleted.destroy(paranoid_tree) + @paranoid_forest_1.paranoid_trees.order(:id).destroy(paranoid_tree.id) + @paranoid_forest_1.paranoid_trees.only_deleted.destroy(paranoid_tree.id) assert_equal 1, @paranoid_forest_1.paranoid_trees(true).count assert_equal 1, @paranoid_forest_1.paranoid_trees(true).with_deleted.count assert_equal 0, @paranoid_forest_1.paranoid_trees(true).only_deleted.count diff --git a/test/test_validations.rb b/test/test_validations.rb index 1208ad8..9f05d3d 100644 --- a/test/test_validations.rb +++ b/test/test_validations.rb @@ -23,19 +23,19 @@ def test_should_validate_without_deleted def test_models_with_scoped_validations_can_be_multiply_deleted model_a = ParanoidWithScopedValidation.create(:name => "Model A", :category => "Category A") model_b = ParanoidWithScopedValidation.create(:name => "Model B", :category => "Category B") - + ParanoidWithScopedValidation.delete([model_a.id, model_b.id]) - + assert_paranoid_deletion(model_a) assert_paranoid_deletion(model_b) end - + def test_models_with_scoped_validations_can_be_multiply_destroyed model_a = ParanoidWithScopedValidation.create(:name => "Model A", :category => "Category A") model_b = ParanoidWithScopedValidation.create(:name => "Model B", :category => "Category B") - + ParanoidWithScopedValidation.destroy([model_a.id, model_b.id]) - + assert_paranoid_deletion(model_a) assert_paranoid_deletion(model_b) end