ruby define_method:如何动态创建带参数的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38233060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
define_method: How to dynamically create methods with arguments
提问by Kostas Andrianos
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.
我想为 find_by 功能创建一堆方法。我不想一遍又一遍地写同样的东西,所以我想使用元编程。
Say I want to create a method for finding by name, accepting the name as an argument. How would I do it? I've used define_method in the past but I didn't have any arguments for the method to take. Here's my (bad) approach
假设我想创建一个按名称查找的方法,接受名称作为参数。我该怎么做?我过去使用过define_method,但我没有任何要采用的方法的参数。这是我的(坏)方法
["name", "brand"].each do |attribute|
define_method("self.find_by_#{attribute}") do |attr_|
all.each do |prod|
return prod if prod.attr_ == attr_
end
end
end
Any thoughts? Thanks in advance.
有什么想法吗?提前致谢。
回答by Jordan Running
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 allmethod returns an Enumerable.)
(我假设该all方法返回一个 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
回答by Albin
It if you read the examples here http://apidock.com/ruby/Module/define_methodyou will find this one:
如果您阅读此处的示例http://apidock.com/ruby/Module/define_method,您会发现以下示例:
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
回答by max pleaner
When you do this: define_method("self.find_by_#{attribute}")
当你这样做时: define_method("self.find_by_#{attribute}")
that is incorrect. The argument to define_method is a symbol with a single word.
这是不正确的。define_method 的参数是一个带有单个单词的符号。
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_brandand find_by_name.
这将产生类的方法find_by_brand和find_by_name。
Note that if you're looking into metaprogramming, this is a good use-case for method_missing. here's a tutorialto use method_missing to implement the same functionality you're going for (find_by_<x>)
请注意,如果您正在研究元编程,这是 method_missing 的一个很好的用例。这是使用 method_missing 实现相同功能的教程( find_by_<x>)

