Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 让ActiveRecord::Base方法的所有子类都说出它们的名称_Ruby On Rails_Ruby_Activerecord - Fatal编程技术网

Ruby on rails 让ActiveRecord::Base方法的所有子类都说出它们的名称

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

出于清除积垢的目的,每当调用某个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