define_method: How to dynamically create methods with arguments

前端 未结 3 1810
梦谈多话
梦谈多话 2020-12-30 20:05

I want to create a bunch of methods for a find_by feature. I don\'t want to write the same thing over and over again so I want to use metaprogramming.

Say I want to

相关标签:
3条回答
  • 2020-12-30 20:22

    When you do this: define_method("self.find_by_#{attribute}")

    that is incorrect. The argument to define_method is a symbol with a single word.

    Let me show you some correct code, hopefully this will be clear:

    class MyClass < ActiveRecord::Base
      ["name", "brand"].each do |attribute|
        define_method(:"find_by_#{attribute}") do |attr_|
          first(attribute.to_sym => attr_)
        end
      end
    end
    

    This will produce class methods for find_by_brand and find_by_name.

    Note that if you're looking into metaprogramming, this is a good use-case for method_missing. here's a tutorial to use method_missing to implement the same functionality you're going for (find_by_<x>)

    0 讨论(0)
  • 2020-12-30 20:24

    It if you read the examples here http://apidock.com/ruby/Module/define_method you will find this one:

    define_method(:my_method) do |foo, bar| # or even |*args|
      # do something
    end
    

    is the same as

    def my_method(foo, bar)
       # do something
    end
    
    0 讨论(0)
  • 2020-12-30 20:31

    If I understand your question correctly, you want something like this:

    class Product
      class << self
        [:name, :brand].each do |attribute|
          define_method :"find_by_#{attribute}" do |value|
            all.find {|prod| prod.public_send(attribute) == value }
          end
        end
      end
    end
    

    (I'm assuming that the all method returns an Enumerable.)

    The above is more-or-less equivalent to defining two class methods like this:

    class Product
      def self.find_by_name(value)
        all.find {|prod| prod.name == value }
      end
    
      def self.find_by_brand(value)
        all.find {|prod| prod.brand == value }
      end
    end
    
    0 讨论(0)
提交回复
热议问题