[英]ruby on rails using bootstrap - prepend text and append button to an input field in a form
[英]Ruby/Rails: Prepend, append code to all methods
我寫了一個小的基准測試類來測試我的代碼進行開發。 目前我必須將Class添加到每個方法的開頭和結尾。 是否可以預先添加,動態附加,以便我不必弄亂我的代碼?
class ApplicationController
before_filter :init_perf
after_filter :write_perf_results_to_log!
def init_perf
@perf ||= Perf.new
end
def write_perf_results_to_log!
@perf.results
end
end
class Products < ApplicationsController
def foo
@perf.log(__methond__.to_s)
caculation = 5 *4
@perf.write!
end
def bar
@perf.log(__methond__.to_s)
caculation = 1 / 5
@perf.write!
end
end
這是Perf類。 它位於services文件夾中。
class Perf
def initialize
@results = []
end
def log(note)
@start = Time.now
@note = note
end
def write!
if @results.find {|h| h[:note] == @note } # Update :sec method exists in results
@results.select { |h| h["note"] == @note; h[":sec"] = (Time.now - @start).round(3) }
else # Add new Hash to results
@results << { :note => @note, :sec => (Time.now - @start).round(3) }
end
end
def results
content = "
PERFORMANCE STATISTICS!
"
@results.each do |r|
content += r[:note] + " " + r[:sec].to_s + "
"
end
content += "
"
Rails.logger.info content
end
end
在一般的計算術語中,您想要做的是稱為代碼檢測 。 有幾種方法可以實現這一點,但是這是使用一些元編程的一個(粗略)示例:
首先定義一個新方法,我們將用它來注入我們的檢測代碼:
class ApplicationController
def self.instrument_methods(*methods)
methods.each { |m|
# Rename original method
self.send(:alias_method, "#{m}_orig", m)
# Redefine old method with instrumentation code added
define_method m do
puts "Perf log #{m}"
self.send "#{m}_orig"
puts "Perf write"
end
}
end
end
如何使用它:
class Product < ApplicationController
def foo
puts "Foo"
end
def bar
puts "Bar"
end
# This has to be called last, once the original methods are defined
instrument_methods :foo, :bar
end
然后:
p = Product.new
p.foo
p.bar
將輸出:
Perf log foo
Foo
Perf write
Perf log bar
Bar
Perf write
以下是一些其他方法來檢測ruby代碼並測量性能:
http://ruby-prof.rubyforge.org/
http://www.igvita.com/2009/06/13/profiling-ruby-with-googles-perftools/
有更好的解決方案。
class ApplicationController
def self.inherited(klass)
def klass.method_added(name)
return if @_not_new
@_not_new = true
original = "original #{name}"
alias_method original, name
define_method(name) do |*args, &block|
puts "==> called #{name} with args: #{args.inspect}"
result = send original, *args, &block
puts "<== result is #{result}"
result
end
@_not_new = false
end
end
end
class Product < ApplicationController
def meth(a1, a2)
a1 + a2
end
end
product = Product.new
puts product.meth(2,3)
結果如下:
==> called meth with args: [2, 3]
<== result is 5
5
來源和解釋如下: http : //pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming 。 我建議不花很多錢來學習這門課程。
我是aspector gem的作者。 感謝dimuch提到它。
我想出了一個使用aspector的解決方案。 以下是高級步驟:
完整的代碼可以在這個要點中找到。 如果您有任何疑問或解決方案沒有達到您的目的,請隨時告訴我。
class PerfAspect < Aspector::Base around options[:action_methods] do |proxy| @perf ||= Perf.new proxy.call @perf.results end around options[:other_methods], :method_arg => true do |method, proxy, *args, &block| @perf.log(method) result = proxy.call *args, &block @perf.write! result end end action_methods = [:action] other_methods = Products.instance_methods(false) - action_methods PerfAspect.apply(Products, :action_methods => action_methods, :other_methods => other_methods)
猜猜aspector gem可以提供幫助。 它沒有很好的文檔記錄,但有一些有用的例子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.