Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

adding support for parent_with_destroyed (i.e. component.android_with…

…_destroyed)
  • Loading branch information...
commit d10004e05ef2ec628e7c0b7fc3d6feeeb06a5775 1 parent 2a7fdd8
Jeffrey Chupp authored
View
26 lib/is_paranoid.rb
@@ -107,6 +107,32 @@ def method_missing name, *args
module InstanceMethods
+ def method_missing name, *args
+ # if we're trying for a _____with_destroyed method
+ # and we can respond to the _____ method
+ # and we have an association by the name of _____
+ if name.to_s =~ /^(.*)(_with_destroyed)$/ and
+ self.respond_to?($1) and
+ (assoc = self.class.reflect_on_all_associations.detect{|a| a.name.to_s == $1})
+
+ parent_klass = Object.module_eval("::#{assoc.class_name}", __FILE__, __LINE__)
+
+ self.class.send(
+ :include,
+ Module.new{ # Example:
+ define_method name do |*args| # def android_with_destroyed
+ parent_klass.find_with_destroyed( # Android.find_with_destroyed(
+ self.send(assoc.primary_key_name) # self.send(:android_id)
+ ) # )
+ end # end
+ }
+ )
+ self.send(name, *args)
+ else
+ super(name, *args)
+ end
+ end
+
# Mark the model deleted_at as now.
def destroy_without_callbacks
self.class.update_all(
View
24 spec/is_paranoid_spec.rb
@@ -10,7 +10,11 @@
@luke = Person.create(:name => 'Luke Skywalker')
@r2d2 = Android.create(:name => 'R2D2', :owner_id => @luke.id)
@c3p0 = Android.create(:name => 'C3P0', :owner_id => @luke.id)
+
@r2d2.components.create(:name => 'Rotors')
+
+ @r2d2.memories.create(:name => 'A pretty sunset')
+ @c3p0.sticker = Sticker.create(:name => 'OMG, PONIES!')
end
describe 'non-is_paranoid models' do
@@ -163,6 +167,23 @@
end
end
+ describe 'accessing destroyed parent models' do
+ it "should be able to access destroyed parents via parent_with_destroyed" do
+ # Memory is has_many with a non-default primary key
+ # Sticker is a has_one with a default primary key
+ [Memory, Sticker].each do |klass|
+ instance = klass.last
+ parent = instance.android
+ instance.android.destroy
+
+ # reload so the model doesn't remember the parent
+ instance.reload
+ instance.android.should == nil
+ instance.android_with_destroyed.should == parent
+ end
+ end
+ end
+
describe 'alternate fields and field values' do
it "should properly function for boolean values" do
# ninjas are invisible by default. not being ninjas, we can only
@@ -171,12 +192,14 @@
ninja.vanish # aliased to destroy
Ninja.first.should be_blank
Ninja.find_with_destroyed(:first).should == ninja
+ Ninja.count.should == 0
# we're only interested in pirates who are alive by default
pirate = Pirate.create(:name => 'Reginald')
pirate.destroy
Pirate.first.should be_blank
Pirate.find_with_destroyed(:first).should == pirate
+ Pirate.count.should == 0
# we're only interested in pirates who are dead by default.
# zombie pirates ftw!
@@ -184,6 +207,7 @@
lambda{
DeadPirate.first.destroy
}.should change(Pirate, :count).from(0).to(1)
+ DeadPirate.count.should == 0
end
end
View
14 spec/models.rb
@@ -6,6 +6,8 @@ class Person < ActiveRecord::Base #:nodoc:
class Android < ActiveRecord::Base #:nodoc:
validates_uniqueness_of :name
has_many :components, :dependent => :destroy
+ has_one :sticker
+ has_many :memories, :foreign_key => 'parent_id'
is_paranoid
@@ -20,13 +22,23 @@ def raise_hell
class Component < ActiveRecord::Base #:nodoc:
is_paranoid
NEW_NAME = 'Something Else!'
-
+
after_destroy :change_name
def change_name
self.update_attribute(:name, NEW_NAME)
end
end
+class Memory < ActiveRecord::Base #:nodoc:
+ is_paranoid
+ belongs_to :android, :class_name => "Android", :foreign_key => "parent_id"
+end
+
+class Sticker < ActiveRecord::Base #:nodoc
+ is_paranoid
+ belongs_to :android
+end
+
class AndroidWithScopedUniqueness < ActiveRecord::Base #:nodoc:
set_table_name :androids
validates_uniqueness_of :name, :scope => :deleted_at
View
12 spec/schema.rb
@@ -21,6 +21,18 @@
t.datetime "updated_at"
end
+ create_table "memories", :force => true do |t|
+ t.string "name"
+ t.integer "parent_id"
+ t.datetime "deleted_at"
+ end
+
+ create_table "stickers", :force => true do |t|
+ t.string "name"
+ t.integer "android_id"
+ t.datetime "deleted_at"
+ end
+
create_table "ninjas", :force => true do |t|
t.string "name"
t.boolean "visible", :default => false
Please sign in to comment.
Something went wrong with that request. Please try again.