How to dynamically create instance methods at runtime?

前端 未结 3 1656
旧时难觅i
旧时难觅i 2021-01-17 18:08

[ruby 1.8]

Assume I have:

dummy \"string\" do
    puts \"thing\" 
end

Now, this is a call to a method which has as

相关标签:
3条回答
  • 2021-01-17 18:28

    use define_method:

    class Bar 
    end
    
    bar_obj = Bar.new
    
    class << bar_obj
     define_method :new_dynamic_method do
      puts "content goes here"
     end
    end
    
    bar_obj.new_dynamic_method
    

    Output:

    content goes here
    
    0 讨论(0)
  • 2021-01-17 18:40

    I'm particularly fond of using method_missing, especially when the code you want to use is very similar across the various method calls. Here's an example from this site - whenever somebody calls x.boo and boo doesn't exist, method_missing is called with boo, the arguments to boo, and (optionally) a block:

    class ActiveRecord::Base
      def method_missing(meth, *args, &block)
        if meth.to_s =~ /^find_by_(.+)$/
          run_find_by_method($1, *args, &block)
        else
          super # You *must* call super if you don't handle the
                # method, otherwise you'll mess up Ruby's method
                # lookup.
        end
      end
    
      def run_find_by_method(attrs, *args, &block)
        # Make an array of attribute names
        attrs = attrs.split('_and_')
    
        # #transpose will zip the two arrays together like so:
        #   [[:a, :b, :c], [1, 2, 3]].transpose
        #   # => [[:a, 1], [:b, 2], [:c, 3]]
        attrs_with_args = [attrs, args].transpose
    
        # Hash[] will take the passed associative array and turn it
        # into a hash like so:
        #   Hash[[[:a, 2], [:b, 4]]] # => { :a => 2, :b => 4 }
        conditions = Hash[attrs_with_args]
    
        # #where and #all are new AREL goodness that will find all
        # records matching our conditions
        where(conditions).all
      end
    end
    

    define_method also looks like it would work for you, but I have less experience with it than method_missing. Here's the example from the same link:

    %w(user email food).each do |meth|
      define_method(meth) { @data[meth.to_sym] }
    end
    
    0 讨论(0)
  • 2021-01-17 18:41

    Yes, there are a few options.

    The first is method_missing. Its first argument is a symbol which is the method that was called, and the remaining arguments are the arguments that were used.

    class MyClass
      def method_missing(meth, *args, &block)
        # handle the method dispatch as you want;
        # call super if you cannot resolve it
      end
    end
    

    The other option is dynamically creating the instance methods at runtime, if you know in advance which methods will be needed. This should be done in the class, and one example is like this:

    class MyClass
      1.upto(1000) do |n|
        define_method :"method_#{n}" do
          puts "I am method #{n}!"
        end
      end
    end
    

    It is a common pattern to have define_method called in a class method which needs to create new instance methods at runtime.

    0 讨论(0)
提交回复
热议问题