cómo simular anotaciones Java como en Ruby?¿Cómo simular anotaciones Java en Ruby?
(vamos que tengo la respuesta, generalizando http://bens.me.uk/2009/java-style-annotations-in-ruby)
cómo simular anotaciones Java como en Ruby?¿Cómo simular anotaciones Java en Ruby?
(vamos que tengo la respuesta, generalizando http://bens.me.uk/2009/java-style-annotations-in-ruby)
Esto se ha adaptado de a piece of code I wrote in an answer to another question hace un par de semanas, aunque por supuesto es apenas original. Este es un conocido lenguaje Ruby, después de todo, que ha estado en uso durante muchos años, por lo menos desde rakes
's desc
método.
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
Aquí hay un pequeño ejemplo:
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
Y, por supuesto, no hay código de Ruby estaría completa sin un banco de pruebas:
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
Su código es más fácil de usar: ¡no requiere que las anotaciones se declaren con anticipación! Una pregunta: ¿ Al almacenar los argumentos de la anotación qué @__last_annotation__[meth[1..-1].to_sym] = args.first
en lugar de @__last_annotation__[meth.to_sym] = args
no puedo coger la metanfetamina bot [1 ..- 1], o bien args.first (no sólo el primer elemento de es la matriz, que empaqueta los argumentos). –
cibercitizen1
@ cibercitizen1: El 'meth [1 ..- 1]' básicamente dice "todo menos el primer caracter del nombre del método", IOW elimina el guión bajo. El 'args.first' es solo porque solo quiero que el método tome un argumento, el hash con la anotación clave-valor-pares. Pero tengo que definir 'method_missing' para tomar una cantidad arbitraria de argumentos solo para poder enviarlos si no quiero manejar el método yo mismo (es decir, si no comienza con un guion bajo). Después de todo, podría haber otras definiciones de 'method_missing' en el sistema para otras DSL o para Rails o algo así. –
@ cibercitizen1: Podría hacer algo más inteligente por supuesto, como comprobar si el tamaño es '1 'y luego desenvolverlo y dejarlo como una matriz. –
Ésta es la intención de uso:
Primero anotaciones en una clase.
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 continuación, le gustaría que examinamos annoations de A la siguiente manera:
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
Bueno. Para ello, necesitará este módulo
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
y se puede definir un conjunto de anotaciones en un módulo de la suya:
module MyAnnotations
def _goodbye(val)
annotate_method(:_goodbye, val)
end
def _hello(val)
annotate_method(:_hello, val)
end
end
o definir a la derecha en la clase que usted está anotando:
create_annotation("_foobar")
Mi requisito es
En una página que muestra una lista de todos los métodos de instancia para una clase ABC, y no debe haber una descripción 1 línea también con todos los métodos
Ahora Yo no sé si es sólo conmigo o almacenar las descripciones de todos los métodos con sus nombres en una nueva tabla en la base de datos suena " súper LAME"
respuesta es - "Anotaciones"
Así es como yo lo hice -
Clase 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
VISTA 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>
espero que ayude!
Antes de esa votación negativa, puede ir a la url citada y marcar que mi respuesta no es una copia sino una simplificación que podría ser útil para otros. (Gracias) – cibercitizen1