如何在ruby中模擬Java-like註釋?如何在Ruby中模擬Java-like註釋?
(我們將我找到了答案,概括 http://bens.me.uk/2009/java-style-annotations-in-ruby)
如何在ruby中模擬Java-like註釋?如何在Ruby中模擬Java-like註釋?
(我們將我找到了答案,概括 http://bens.me.uk/2009/java-style-annotations-in-ruby)
這是幾個星期前從a piece of code I wrote in an answer to another question改編的,雖然它當然不是原創的。這是一個着名的Ruby成語,畢竟這已經在使用多年,至少從rakes
的desc
的方法。
module Annotations
def annotations(meth=nil)
return @__annotations__[meth] if meth
@__annotations__
end
private
def method_added(m)
(@__annotations__ ||= {})[m] = @__last_annotation__ if @__last_annotation__
@__last_annotation__ = nil
super
end
def method_missing(meth, *args)
return super unless /\A_/ =~ meth
@__last_annotation__ ||= {}
@__last_annotation__[meth[1..-1].to_sym] = args.size == 1 ? args.first : args
end
end
class Module
private
def annotate!
extend Annotations
end
end
這裏有一個小例子:
class A
annotate!
_hello color: 'red', ancho: 23
_goodbye color: 'green', alto: -123
_foobar color: 'blew'
def m1; end
def m2; end
_foobar color: 'cyan'
def m3; end
end
當然沒有Ruby代碼將是不完整的測試套件:
require 'test/unit'
class TestAnnotations < Test::Unit::TestCase
def test_that_m1_is_annotated_with_hello_and_has_value_red
assert_equal 'red', A.annotations(:m1)[:hello][:color]
end
def test_that_m3_is_annotated_with_foobar_and_has_value_cyan
assert_equal 'cyan', A.annotations[:m3][:foobar][:color]
end
def test_that_m1_is_annotated_with_goodbye
assert A.annotations[:m1][:goodbye]
end
def test_that_all_annotations_are_there
annotations = {
m1: {
hello: { color: 'red', ancho: 23 },
goodbye: { color: 'green', alto: -123 },
foobar: { color: 'blew' }
},
m3: {
foobar: { color: 'cyan' }
}
}
assert_equal annotations, A.annotations
end
end
您的代碼使用更簡單:它不需要提前聲明註釋!一個問題: 當存儲的註釋的參數 爲什麼@__last_annotation__[meth[1..-1].to_sym] = args.first
代替@__last_annotation__[meth.to_sym] = args
我不能趕上機器人甲基[1 ..- 1],或任一args.first(是不是隻的第一個元素數組,包裝參數)。 –
cibercitizen1
2010-07-01 22:05:00
@ cibercitizen1:'meth [1 ..- 1]'基本上是說「除了方法名的第一個字符之外的所有東西」,IOW它刪除了下劃線。 'args.first'只是因爲我只想讓方法接受一個參數,散列與註釋鍵值對。但是我必須定義'method_missing'來取任意數量的參數,以便我可以發送它們,如果我不想自己處理這個方法(即它不是以下劃線開頭的話)。畢竟,在其他DSL或Rails或其他系統中可能存在系統中method_missing的其他定義。 – 2010-07-01 22:43:33
@ cibercitizen1:你當然可以做更聰明的事情,比如檢查大小是否爲1,然後解開它,否則就把它作爲一個數組。 – 2010-07-01 22:44:41
這是預期用途:
首先,你標註的類。
class A
extend Annotations
extend MyAnnotations
create_annotation("_foobar")
_hello({:color=>'red', :ancho=>23})
_goodbye({:color=>'green', :alto=>-123})
_foobar({:color=>'blew'})
def m1
end
def m2
end
_foobar({:color=>'cyan'})
def m3
end
end
然後,你想不檢查A的annoations這樣的:
anots = A.annotations
puts anots.keys
puts anots[:m1][:_hello][:color]
puts anots[:m3][:_foobar][:color]
puts anots[:m1].key?(:_goodbye)
puts "---------------"
anots.each do |met| # each annotated method
puts "-- annotated method --"
puts met[0] # method name
met[1].each do |a| # each annotation for the method
puts "-> " + a[0].to_s # annotation name
a[1].each do |par| # each pair: key-value
puts " key=" + par[0].to_s + " value=" + par[1].to_s
end
end
end
嘛。要做到這一點,你需要這個模塊
module Annotations
@@annotation_list = {}
@@pending = {}
def method_added(met_sym)
#puts "-> adding " + met_sym.to_s + " to class + self.to_s
if @@pending.size > 0
#puts met_sym.to_s + " is annotated "
@@annotation_list[met_sym] = @@pending
#puts @@annotation_list
else
#puts met_sym.to_s + " is not annotated "
end
@@pending = {}
end
def annotate_method(a,b)
@@pending[a] = b
end
def create_annotation(anot_sym)
code = "def #{anot_sym.to_s}(val)
annotate_method(:#{anot_sym} ,val)
end"
instance_eval code
end
def annotations
return @@annotation_list
end
end
,你可以你的模塊中定義的一組註解:
module MyAnnotations
def _goodbye(val)
annotate_method(:_goodbye, val)
end
def _hello(val)
annotate_method(:_hello, val)
end
end
或將其定義直接進入你註釋類:
create_annotation("_foobar")
我的要求是
在一個第I頁顯示了ABC類的所有instance_methods的列表並且應該有一個1行描述過在每次方法
現在,我不知道這是否只是我或存儲的描述對所有與他們的名字在DB這些方法在一個新的表音「超級LAME」
答案是 - 「集註」
以下是我做到了 -
個ABC類激活的功能。RB
class Abc
extend Annotations
create_annotation("_annotation")
_annotation({:description=>"Info e-mail address"})
def info_email
APP_CONFIG['info_email']
end
_annotation({:description=>"Location of order"})
def location
unless self.order.blank?
@location ||= self.order.location.description
end
end
VIEW methods_list.html.erb
<html>
<head>
</head>
<body>
<% default_description = "Description not specified" %>
<% Abc.instance_methods.each do |method| %>
<span style="float:right">
<%= (Abc.annotations[method.to_sym].present?
?
(Abc.annotations[method.to_sym][:_annotation][:description].blank?
? default_description :
Abc.annotations[method.to_sym][:_annotation][:description])
: default_description) %>
</span>
<% end %>
</body>
</html>
希望它能幫助!
在此之前,您可以前往引用的網址並檢查 我的回覆不是它的副本,而是簡化,對其他人可能有用。 (謝謝) – cibercitizen1 2010-07-01 12:07:42