这是我遇到的一个小问题。请注意,这是一个简化的示例。
假设我有一个包含多个实例方法的类,我想使用ActiveSupport::Concern
记录其中一个实例方法:
class Car
include LogStartEngine
def start_engine
# useful thing
end
def check_oil
# useful thing
end
def open_doors
# useful thing
end
end
以下是我首先提出的问题:
module LogStartEngine
extend ActiveSupport::Concern
included do
alias_method_chain :start_engine, :logging
end
def start_engine_with_logging
Rails.logger.info("Starting engine!")
start_engine_without_logging
Rails.logger.info("Engine started!")
end
end
但这会导致
NameError: undefined method `start_engine' for class `Car'
from /Users/david/.gem/ruby/1.9.3/gems/activesupport-4.0.3/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method'
这是可以理解的,因为当包含LogStartEngine
时,类Car
没有任何名为start_engine
的方法。
我知道我可以在方法include LogStartEngine
之后解决此问题start_engine
,但我想将此声明保留在原来的位置。
所以约束是:
start_engine
,而不记录所有方法。Car
只需要包含LogStartEngine
个问题。我想避免因为关注而添加任何自定义帮助方法,例如log_method :start_engine
。include LogStartEngine
语句保留在原来的位置。我不希望它低于方法start_engine
或在课程结束时。Module#prepend
不是有效的解决方案:)答案 0 :(得分:1)
经过一些试验,这是我的解决方案:
module LogStartEngine
extend ActiveSupport::Concern
module ClassMethods
def method_added(_)
unless instance_methods.include?(:start_engine_without_logging)
alias_method_chain :start_engine, :logging
end
end
end
def start_engine_with_logging
Rails.logger.info("Starting engine!")
start_engine_without_logging
Rails.logger.info("Engine started!")
end
end
我的子问题是:还有其他方法可以实现吗?
答案 1 :(得分:0)
另一种方法是使用委托或使用http://www.ruby-doc.org/stdlib-2.0/libdoc/forwardable/rdoc/Forwardable.html - 然后你可以组合你的对象并将它们组合起来,我也假设你可以使用method_missing
或类似的东西来提供"自动& #34;记录器。
class Car
def start_engine
# wrooom
end
end
class CarWithLogging
attr_reader :car
def initialize(car)
@car = car
end
def start_engine
Rails.logger.info "starting engine"
car.start_engine
Rails.logger.info "engine started"
end
end
car = CarWithLogging.new(Car.new)
car.start_engine
更新:作为替代方案,您可以使用Ruby的prepend
(仅在2.0之后可用),因此实际上不需要AS :: Concern。
class Car
prepend CarLogging
def start_engine; end
end
module CarLogging
def start_engine
puts "before"
super
puts "after"
end
end