Я не очень понимаю, зачем вам снова определять ассоциации в подклассах.Тем не менее, у меня есть совет, который вы можете использовать непосредственно в вашей Subscription
модели.
Если вы хотите сохранить свою модель простой и не перегружать ее логикой обратных вызовов, вы можете создать Класс обратного вызова , чтобы обернуть всю логику, которая будет использоваться моделью.
Для этого вам нужно создать класс, например:
class SubscriptionCallbacks
def self.after_create(subscription)
log_sub(subscription)
end
def self.after_destroy(subscription)
log_unsub_reason(subscription)
end
end
Затемв Subscription
модель:
class Subscription < ApplicationRecord
belongs_to :list
belongs_to :subscriber
after_destroy SubscriptionCallbacks
after_create SubscriptionCallbacks
end
Таким образом, ваша модель станет чистой, и вы сможете destroy
подписаться и применять всю пользовательскую логику без использования службы.
ОБНОВЛЕНИЕ
В частности, я не понимаю, почему вы делаете наследование одной таблицы на трех моделях, чтобы добавить обратные вызовы для одной из них.То, как вы написали свой вопрос, для трех подклассов вы переопределяете ассоциации, чтобы использовать созданные подклассы.Это действительно необходимо?Я думаю, что нет, потому что то, что вы хотите достичь, - это просто рефакторинг вашего сервиса в качестве обратных вызовов, чтобы использовать destroy
и destroy_all
непосредственно в модели Subscription
, я беру это отсюда:
Но я нахожу это все более неловким.Я не могу использовать естественный subscriber.subscription.destroy_all, например, но должен быть осторожен, чтобы пройти методы SubscriptionManager вместо этого.
Может быть, с условных обратных вызовов достаточно,или даже обычные обратные вызовы в вашей Subscription
модели.
Я не знаю, как пишется реальный код, но я обнаружил, что сложно использовать Single Table Inheritance просто для добавления обратных вызовов.Это не делает ваши модели «простыми и гибкими».
ОБНОВЛЕНИЕ 2
В классе обратного вызова вы определяете методы с именем обратного вызова, который вы хотитереализовать и передать subscription
в качестве параметра.Внутри этих методов вы можете создать всю логику, какую захотите.Например (при условии, что вы будете использовать другую логику с атрибутом type
):
class SubscriptionCallbacks
def after_create(subscription)
if subscription.type == 'foo'
log_foo_sub(subscription)
elsif subscription.type == 'bar'
log_bar_sub(subscription)
end
end
private
def log_foo_sub(subscription)
# Here will live all the logic of the callback for subscription of foo type
end
def log_bar_sub(subscription)
# Here will live all the logic of the callback for subscription of bar type
end
end
Это может быть много логики, которая не будет записана в модели Subscription
.Вы можете использовать destroy
и destroy_all
как обычно, и если тип подписки не определен в if else
, тогда ничего не произойдет.
Вся логика обратных вызовов будет заключена в callback class
, и единственный код, который вы добавите к модели subscription
, будет:
class Subscription < ApplicationRecord
belongs_to :list
belongs_to :subscriber
after_create SubscriptionCallbacks.new
end