ruby alias_method в методе класса
Кажется, что alias_method не работает в блоке класса << сам по себе так же, как снаружи. В частности, когда я использую alias_method для метода экземпляра и впоследствии перезаписываю метод, псевдоним можно использовать для доступа к исходному методу. Однако я не могу сделать это с помощью метода класса.
Это мой вариант использования: я переопределяю методы destroy и destroy_all, которые унаследованы от базы ActiveRecord, потому что код, как написано в настоящее время, позволяет очень легко случайно удалить строки, когда вы намеревались удалить записи соединения. Этот дизайн может измениться в более крупном проекте, но сейчас это мое решение, поскольку по большей части никто не захочет удалять строки из этой таблицы. Но для того, чтобы разрешить намеренное удаление строк в таблице для благих намерений, я использую alias_method, чтобы сохранить дескриптор оригинальных методов destroy и destroy_all. Использование псевдонима работает для доступа к оригинальному методу: destroy (instance), но не позволяет мне получить доступ к оригинальному методу: desotry_all (class)
class HoldReason < ActiveRecord::Base
class << self
alias_method :remove_hold_reasons_from_table, :destroy_all
def destroy_all
raise "Nope"
end
end
alias_method :remove_hold_reason, :destroy
def destroy
raise "Nope"
end
end
Здесь мы видим, что хотя эта стратегия работает для метода экземпляра, чтобы разрешить успешное удаление одной строки:
> HoldReason.find_by(title: "Management Review").remove_hold_reason
HoldReason Load (0.7ms) SELECT `hold_reasons`.* FROM `hold_reasons` WHERE `hold_reasons`.`title` = 'Management Review' LIMIT 1
(0.5ms) BEGIN
SQL (4.6ms) DELETE FROM `hold_reasons` WHERE `hold_reasons`.`id` = 23
(0.6ms) COMMIT
=> #<HoldReason id: 23, title: "Management Review", category: "Operations">
Я не могу получить доступ к оригинальному методу: destroy_all для удаления нескольких строк в одном запросе; вместо этого я получаю переопределенный метод, даже когда я использую псевдоним:
> HoldReason.remove_hold_reasons_from_table
HoldReason Load (0.7ms) SELECT `hold_reasons`.* FROM `hold_reasons`
RuntimeError: Nope
Что происходит, что я не могу сделать это для методов класса, и как я могу это исправить (кроме просто использовать необработанный запрос SQL для удаления)?
1 ответ
Ответ в том, что я не получал новый метод: destroy_all; Я правильно получал старый метод: destroy_all, и он назывался: уничтожить под капотом. Конечно, вызвав: destroy, он получил новый метод: destroy, который вызвал ошибку. Таким образом, казалось, что я получаю новый метод класса, потому что новый метод класса и новый метод экземпляра вызывают точно такую же ошибку.
Это станет понятнее, если я немного изменю это:
class HoldReason < ActiveRecord::Base
class << self
alias_method :remove_hold_reasons_from_table, :destroy_all
def destroy_all
raise "Don't destroy_all (multiple: class method)"
end
end
alias_method :remove_hold_reason, :destroy
def destroy
raise "Don't destroy (single: instance method)"
end
end
результаты в
> HoldReason.remove_hold_reasons_from_table
RuntimeError: Don't destroy (single: instance method)