问题
My Goal:
Override the #destroy method in rails so that gems like Devise will perform a soft-delete.
My Attempt:
def destroy(mode = :soft)
if mode == :hard
super
else
... soft-delete actions ...
end
end
When this is called on the object it get...
ArgumentError: wrong number of arguments (1 for 0)
I would like for this to default to soft-deleting, but have the option to fully destroy the object. My approach may not be the best way to do this, but any advice would help.
回答1:
It should be
super()
Here's the full implementation
def destroy(mode = :soft)
if mode == :hard
super()
else
... soft-delete actions ...
end
end
The reason is because when you call super without passing any argument, Ruby will call the parent method passing the same arguments that are passed to the original method.
But because the original destroy method in Rails takes no argument, the result is the error
ArgumentError: wrong number of arguments (1 for 0)
because your call is translated into
if mode == :hard
super(mode)
Using super() (with empty ()) forces Ruby to pass no arguments to the parent method.
As a side note, I normally prefer to "rename" the old object, instead of overriding it.
alias _destroy destroy
def destroy(mode = :soft)
if mode == :hard
_destroy
else
... soft-delete actions ...
end
end
In this way you will still retain a reference to the original _destroy.
Even better, I prefer to expose a custom API instead of overriding Rails default methods. It helps me to expose a custom API loosely coupled to ActiveRecord internals.
来源:https://stackoverflow.com/questions/20553576/overriding-rails-destroy-argument-error