Skip to content

Commit

Permalink
method_missing is no longer overridden on instances provided you decl…
Browse files Browse the repository at this point in the history
…are your custom method_missing *before* specifying the model is_paranoid
  • Loading branch information
Jeffrey Chupp committed May 20, 2009
1 parent 967510b commit bc929ad
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
23 changes: 16 additions & 7 deletions lib/is_paranoid.rb
Expand Up @@ -86,7 +86,7 @@ def restore(id, options = {})

# find_with_destroyed and other blah_with_destroyed and
# blah_destroyed_only methods are defined here
def method_missing name, *args
def method_missing name, *args, &block
if name.to_s =~ /^(.*)(_destroyed_only|_with_destroyed)$/ and self.respond_to?($1)
self.extend(Module.new{
if $2 == '_with_destroyed'
Expand All @@ -110,16 +110,16 @@ def method_missing name, *args
define_method name do |*args|
self.with_exclusive_scope do
with_scope({:find => { :conditions => ["#{self.table_name}.#{destroyed_field} IS NOT ?", field_not_destroyed] }}) do
self.send($1, *args)
self.send($1, *args, &block)
end
end
end

end
})
self.send(name, *args)
self.send(name, *args, &block)
else
super(name, *args)
super(name, *args, &block)
end
end

Expand All @@ -140,8 +140,17 @@ def restore_related klass, key_name, id, options #:nodoc:
end

module InstanceMethods
def self.included(base)
base.class_eval do
unless method_defined? :method_missing
def method_missing(meth, *args, &block); super; end
end
alias_method :old_method_missing, :method_missing
alias_method :method_missing, :is_paranoid_method_missing
end
end

def method_missing name, *args
def is_paranoid_method_missing name, *args, &block
# 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 _____
Expand All @@ -164,9 +173,9 @@ def method_missing name, *args
end # end
}
)
self.send(name, *args)
self.send(name, *args, &block)
else
super(name, *args)
old_method_missing(name, *args, &block)
end
end

Expand Down
9 changes: 9 additions & 0 deletions spec/is_paranoid_spec.rb
Expand Up @@ -198,6 +198,15 @@
sticker.android.should == nil
sticker.android_with_destroyed.should == nil
end

it "should not break method_missing's defined before the is_paranoid call" do
# we've defined a method_missing on Sticker
# that changes the sticker name.
sticker = Sticker.new(:name => "Ponies!")
lambda{
sticker.some_crazy_method_that_we_certainly_do_not_respond_to
}.should change(sticker, :name).to(Sticker::MM_NAME)
end
end

describe 'alternate fields and field values' do
Expand Down
8 changes: 8 additions & 0 deletions spec/models.rb
Expand Up @@ -42,6 +42,14 @@ class Memory < ActiveRecord::Base #:nodoc:
end

class Sticker < ActiveRecord::Base #:nodoc
MM_NAME = "You've got method_missing"

# this simply serves to ensure that we don't break method_missing
# if it is implemented on a class and called before is_paranoid
def method_missing name, *args, &block
self.name = MM_NAME
end

is_paranoid
belongs_to :android
end
Expand Down

0 comments on commit bc929ad

Please sign in to comment.