Я читаю Rails 4 way (автор Obie Fernandez), известная книга о Rails, и из того, что я читал до сих пор, я может очень рекомендовать его.
Однако есть примерный раздел 9.2.7.1: Несколько методов обратного вызова в одном классе, который меня смущает:
Потерпите меня, чтобы проблема была ясна для всех, я воспроизвел шаги, описанные в этом вопросе в книге.
В разделе описываются обратные вызовы Active Record (before_create
, before_update
и т.д.) и что можно создать класс, который обрабатывает несколько обратных вызовов для вас. Перечисленный код выглядит следующим образом:
class Auditor
def initialize(audit_log)
@audit_log = audit_log
end
def after_create(model)
@audit_log.created(model.inspect)
end
def after_update(model)
@audit_log.updated(model.inspect)
end
def after_destroy(model)
@audit_log.destroyed(model.inspect)
end
end
В книге говорится, что для добавления этого журнала аудита в класс Active Record вы должны сделать следующее:
class Account < ActiveRecord::Base
after_create Auditor.new(DEFAULT_AUDIT_LOG)
after_update Auditor.new(DEFAULT_AUDIT_LOG)
after_destroy Auditor.new(DEFAULT_AUDIT_LOG)
...
end
В книге затем отмечается, что этот код очень уродлив, нужно добавить трех аудиторов на три строки и что он не СУХОЙ. Затем он идет вперед и говорит нам, что для решения этой проблемы мы должны обезвредить метод acts_as_audited
в Active Record::Base
объект следующим образом:
(книга предлагает поместить этот файл в /lib/core_ext/active_record_base.rb
)
class ActiveRecord::Base
def self.acts_as_audited(audit_log=DEFAULT_AUDIT_LOG)
auditor = Auditor.new(audit_log)
after_create auditor
after_update auditor
after_destroy auditor
end
end
который позволяет вам написать класс модели учетных записей следующим образом:
class Account < ActiveRecord::Base
acts_as_audited
...
end
Прежде чем читать книгу, я уже сделал нечто подобное, что добавляет функциональность нескольким моделям Active Record. Техника, которую я использовал, заключалась в создании модуля. Чтобы остаться с примером, то, что я сделал, было похоже на:
(я бы поставил этот файл внутри /app/models/auditable.rb
)
module Auditable
def self.included(base)
@audit_log = base.audit_log || DEFAULT_AUDIT_LOG #The base class can override it if wanted, by specifying a self.audit_log before including this module
base.after_create audit_after_create
base.after_update audit_after_update
base.after_destroy audit_after_destroy
end
def audit_after_create
@audit_log.created(self.inspect)
end
def audit_after_update
@audit_log.updated(self.inspect)
end
def audit_after_destroy
@audit_log.destroyed(self.inspect)
end
end
Обратите внимание, что этот файл заменяет метод Auditor
и обезглавленный ActiveRecord::Base
. Класс Account
будет выглядеть следующим образом:
class Account < ActiveRecord::Base
include Auditable
...
end
Теперь вы прочли и то, как это делает книга, и то, как я бы это сделал в прошлом. Мой вопрос: Какая версия более устойчива в долгосрочной перспективе? Я понимаю, что это немного упрямый вопрос, как и все о Rails, но чтобы он был ответственным, я в основном хочу знать:
- Почему вы хотите обезьян-патч
ActiveRecord::Base
напрямую, за создание и включениеModule
?