论坛首页 编程语言技术论坛

module中的函数重定义之后,如何re-mixins?

浏览 4299 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-08-14  
   需要在页面上输出每次require的调用时间。于是修改了 rails中的一个 方法,方法是module的一部分 。但是 如何remixins,却是大问题了。

或者另外一个方法直接修改 mixins以后的代码。 但是嵌套了多个module之后, 不清楚怎么去修改这个方法了。

以下是代码


module ActionController #:nodoc:
  module Benchmarking #:nodoc:
    module ClassMethods

      def perform_action_with_benchmark
        unless logger
          perform_action_without_benchmark
        else
          runtime = [Benchmark::measure{ perform_action_without_benchmark }.real, 0.0001].max
          @runtime_require = runtime #这句是添加的代码

          log_message  = "Completed inaa #{sprintf("%.5f", runtime)} (#{(1 / runtime).floor} reqs/sec)"
          log_message << rendering_runtime(runtime) if defined?(@rendering_runtime)
          log_message << active_record_runtime(runtime) if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
          log_message << " | #{headers["Status"]}"
          log_message << " [#{complete_request_uri rescue "unknown"}]"
          logger.info(log_message)
        end
      end
    end
  end
end




   发表时间:2007-08-14  
ruby是open class的编程语言,不需要re-mixin。

你在rails项目的lib目录下面创建同名文件(注意保持路径结构),然后其他部分都空着,只把你要改写的方法部分按照你改好的样式写进去就行了。
 module ActionController #:nodoc:  
   module Benchmarking #:nodoc:  
     module ClassMethods  
   
       def perform_action_with_benchmark  
         .........
         ........  # code here
        end
      end
    end
 end



rails项目启动以后先读入系统原来定义的方法,随后读取到你在lib目录下面同名文件,就打开了该方法定义,用你定义的方法覆盖之,其余部分保持原样。

这便是open class方便之处阿,修改系统类库跟玩似的。
0 请登录后投票
   发表时间:2007-08-14  
哦,要写在lib目录下面的啊, 我一直在 application.rb中尝试操作,试了很多办法都不行。



尝试  建立 以下文件
myproject\lib\action_controller\benchmarking.rb
myproject\lib\actionpack\lib\action_controller\benchmarking.rb


没有重新覆盖代码。  看rails的初始化代码,的确会加载这里的代码,不过怎么不会覆盖。 路径不对吗?
0 请登录后投票
   发表时间:2007-08-14  
这个文件我看了一下,貌似只覆盖一个方法是不行的。因为他是定义moudule被include的时候,注入给action一堆单例方法的。好在这个文件不大,只有89行,你就把benchmarking.rb整个拷贝到rails_proejct/lib/action_controller/benchmarking.rb就可以了,然后改你要改的内容。
0 请登录后投票
   发表时间:2007-08-15  
呵呵,还是有问题。改过的代码都没有被load, 特意多写了个end在代码中,启动的时候也没有报错。看来文件放的位置还有问题。


直接require修改过的代码
然后模仿  ActionController load时候的代码

ActionController::Base.class_eval do
  include ActionController::Benchmarking
end

在application.rb中加入下面的代码
ApplicationController.class_eval do
  include ActionController::Benchmarking
end

出现循环调用, stack撑破。

看来只有最后一招了 
0 请登录后投票
   发表时间:2007-08-15  
我试过了,把benchmarking.rb整个文件放在lib下面,改代码,可以生效,一切正常。
0 请登录后投票
   发表时间:2007-08-17  
我也有跟楼主一样的问题:
我想修改ActionView::Helpers::NumberHelper下的number_helper.rb文件中一个actionview方法的默认值
ruby 代码
  1. number_with_precision(number, precision=3)  

变成
ruby 代码
  1. number_with_precision(number, precision=2) 

我尝试将整个number_helper.rb修改后复制到rails_project/lib/actionpack/lib/action_view/helpers/number_helper.rb
或者rails_project/lib/action_view/helpers/number_helper.rb
都不工作,我现在能想到的办法是在rails_project/app/helpers/application_helper.rb中重写这个方法,在这里的确会将已经min-in的静态方法给override掉,但是这个办法用多了可能会让application_helper变得混乱.
0 请登录后投票
   发表时间:2007-11-21  
今天刚好也有这个需求,我是这样实现的:
# file: /app/application.rb
class ApplicationController < ActionController::Base
  include AppendBenchmarking
end

# file: /lib/append_benchmarking.rb
module AppendBenchmarking #:nodoc:

  def self.included(klass)
    # 在Rails似乎不能直接覆盖掉alias_method得到的方法(指perform_action_with_benchmark),所以还是要再用alias一次
    klass.class_eval do
      alias_method_chain :perform_action, :append_benchmark
    end
  end
    
  def perform_action_with_append_benchmark
    unless logger
      perform_action_without_benchmark
    else
      runtime = [Benchmark::measure{ perform_action_without_benchmark }.real, 0.0001].max
      log_message  = "Completed in #{sprintf("%.5f", runtime)} (#{(1 / runtime).floor} reqs/sec)"
      log_message << rendering_runtime(runtime) if defined?(@rendering_runtime)
      log_message << active_record_runtime(runtime) if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
      log_message << " | #{headers["Status"]}"
      log_message << " [#{complete_request_uri rescue "unknown"}]"
      log_message << " append some benchmark message here"
      logger.info(log_message)
    end
  end

 end

在development模式下即改即生效
oops,忘了高亮代码,亮了
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics