使用Ruby我知道你可以通过命名方法获得相当的创意。例如,在rails中,您有.find_by_this_and_that
。
我该怎么做?
示例:的
def get_persons_with_5_things
res = []
persons.each do |person|
if person.number_of_things == %MAGICALLY GET THE NUMBER 5 FROM FUNCTION NAME%
res << person
end
end
return res
end
我甚至不确定你如何称呼这类东西,所以任何指针都会受到赞赏。
答案 0 :(得分:10)
我对你的例子感到有些困惑。如果在方法名称中使用硬编码5定义方法,则不需要在方法体内进行神奇地计算。如果你想用缺少方法做一些动态的东西,那就是这样的:
def method_missing(name, *args)
if name.to_s =~ /get_persons_with_(\d+)_things/
number_of_things = $1.to_i
res = []
persons.each do |person|
if person.number_of_things == number_of_things
res << person
end
end
return res
else
return super(name, *args)
end
end
[EDIT(JörgWMittag)]:这是一种更为Rubyish的方法来实现相同的方法:
def method_missing(name, *args)
return super unless name.to_s =~ /get_persons_with_(\d+)_things/
number_of_things = $1.to_i
return persons.select {|person| person.number_of_things == number_of_things }
end
super
只传递原始参数,不需要明确传递它们return
或if
表达式保护的早期unless
可以大大清除控制流程each
迭代器都是,根据谓词选择项目;但是,已经存在用于选择项目的迭代器:select
答案 1 :(得分:5)
Ruby有不同的元编程技术来做这种事情。
首先我们需要变量方法
class DB
def get_persons_with_x_things(x)
res = []
persons.each do |person|
if person.number_of_things == x
res << person
end
end
return res
end
end
如果有一定数量的x。我们可以使用define_method
来创建所有这些方法。 define_method
创建了一个方法。第一个参数是方法的名称,第二个参数或给定的块是东西,它们在调用方法时执行。
这样,您不会真正创建这样的方法,但是如果用户调用它,它将查找用户,就像它存在一样。但是,如果用户依赖Object#methods
等,他将永远不会看到你无数的虚假方法。
class DB
99.times do |i|
define_method("get_persons_with_#{i}_things") do
get_persons_with_x_things(i)
end
end
end
如果有一个x method_missing
的无限numbor将更适合这个任务。如果有人试图调用不存在的方法,则执行method_missing
。 method_missing
的第一个参数是方法名称作为符号,以下参数是原始参数。
class DB
def method_missing(name, *args)
case name.to_s
when /^get_persons_with_(\d+)_things$/
get_persons_with_x_things($1.to_i)
else
super(name, *args)
end
end
end
不使用静态regexe会更酷。但这可能会带来一些安全隐患。我在这里使用的方法send
通过它的名称调用方法。
class DB
def method_missing(name, *args)
name.to_s=~ /\d+/
# always be carefull with $ variables, they are global for this thread, so save everything as fast as you can
new_name= "#{$`}x#{$'}"
number= $1.to_i
if method_defined?(new_name)
send(new_name, number)
else
super(name, *args)
end
end
end
答案 2 :(得分:1)
答案 3 :(得分:1)
看一下Ruby的callbacks特别是method_missing。