How to simulate Java-like annotations in Ruby?

后端 未结 3 1039
太阳男子
太阳男子 2020-12-05 14:37

How to simulate Java-like annotations in ruby?

(We\'ll I have the answer, generalizing http://bens.me.uk/2009/java-style-annotations-in-ruby)

3条回答
  •  攒了一身酷
    2020-12-05 15:04

    This is adapted from a piece of code I wrote in an answer to another question a couple of weeks ago, although it is of course hardly original. This is a well-known Ruby idiom, after all, which has been in use for many years, at least since rakes's desc method.

    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
    

    Here's a small example:

    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
    

    And of course no Ruby code would be complete without a testsuite:

    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
    

提交回复
热议问题