Ruby on rails 让ActiveRecord::Base方法的所有子类都说出它们的名称
出于清除积垢的目的,每当调用某个AR模型中的方法时,我都要记录日志 我可以通过这样的方式获得所有这些课程:Ruby on rails 让ActiveRecord::Base方法的所有子类都说出它们的名称,ruby-on-rails,ruby,activerecord,Ruby On Rails,Ruby,Activerecord,出于清除积垢的目的,每当调用某个AR模型中的方法时,我都要记录日志 我可以通过这样的方式获得所有这些课程: subclasses = [] ; ObjectSpace.each_object(Module) {|m| subclasses << m if m.ancestors.include? ActiveRecord::Base } ; subclasses.map(&:name) 我如何才能做到这一点,而不将其实际添加到每个方法中 也许有一些很棒的meta?你有 AR
subclasses = [] ; ObjectSpace.each_object(Module) {|m| subclasses << m if m.ancestors.include? ActiveRecord::Base } ; subclasses.map(&:name)
我如何才能做到这一点,而不将其实际添加到每个方法中
也许有一些很棒的meta?你有
AR::Base.instance_方法
及
AR::Base.class_eval“some string”
因此,您可能可以使用它们在每个现有方法上放置一个头。例如,方法调用,您可以使用以下代理模式:
class BlankSlate
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
end
class MyProxy < BlankSlate
def initialize(obj, &proc)
@proc = proc
@obj = obj
end
def method_missing(sym, *args, &block)
@proc.call(@obj,sym, *args)
@obj.__send__(sym, *args, &block)
end
end
其灵感来源于:
您需要找到一种方法在ActiveRecord::Base对象创建中应用此模式。如果只需要类中定义的方法,则可以执行以下操作:
>> Project.instance_methods
=> ["const_get", "validates_associated", "before_destroy_callback_chain", "reset_mocha", "parent_name", "inspect", "slug_normalizer_block", "set_sequence_name", "require_library_or_gem", "method_exists?", "valid_keys_for_has_and_belongs_to_many_association=", "table_name=", "validate_find_options_without_friendly", "quoted_table_name" (another 100 or so methods)]
只有在类中定义的方法
>> Project.instance_methods(false)
=> ["featured_asset", "category_list", "before_save_associated_records_for_slugs", "asset_ids", "primary_asset", "friendly_id_options", "description", "description_plain"]
为此,您应该使用面向方面的编程模式。在Ruby中提供了AOP DSL 在
config/initializers/
目录中创建log\u method\u initializer.rb
require 'aquarium'
Aspect.new(:around, :calls_to => :all_methods,
:in_types => [ActiveRecord::Base] ) do |join_point, object, *args|
log "Entering: #{join_point.target_type.name}##{join_point.method_name}"
result = join_point.proceed
log "Leaving: #{join_point.target_type.name}##{join_point.method_name}"
result
end
从
ActiveRecord::Base继承的类的每个方法调用都将被记录。对于水族馆,似乎添加了method\u options=>:exclude\u祖先\u方法
起到了作用。
我也有堆栈太深的问题
来源
我更新了我的问题,使之更清楚一点——很抱歉,我添加了代理obj作为块的参数。这样,调用直接对象方法就更容易了。这不是开箱即用的,我必须在require语句之后包含水族馆::方面。另外,现在User.first生成一个SystemStackError:堆栈级别太深-所以有些东西是递归的。但如果我能让它发挥作用,我喜欢它的发展方向。
>> Project.instance_methods(false)
=> ["featured_asset", "category_list", "before_save_associated_records_for_slugs", "asset_ids", "primary_asset", "friendly_id_options", "description", "description_plain"]
require 'aquarium'
Aspect.new(:around, :calls_to => :all_methods,
:in_types => [ActiveRecord::Base] ) do |join_point, object, *args|
log "Entering: #{join_point.target_type.name}##{join_point.method_name}"
result = join_point.proceed
log "Leaving: #{join_point.target_type.name}##{join_point.method_name}"
result
end