6

我有一个正在开发的命令行 Ruby 应用程序,我想允许它的用户提供将作为过滤器运行在部分流程上的代码。基本上,应用程序这样做:

  1. 读入一些数据
  2. 如果指定了过滤器,则使用它来过滤数据
  3. 处理数据

我希望过滤过程(步骤 2)尽可能灵活。

我的想法是,用户可以提供一个 Ruby 文件,该文件设置一个已知常量以指向实现我定义的接口的对象,例如:

# user's filter

class MyFilter
  def do_filter(array_to_filter)
    filtered_array = Array.new
    # do my filtering on array_to_filter
    filtered_array
end 

FILTER = MyFilter.new

然后,我的应用程序代码将执行以下操作:

array_that_might_get_filtered = get_my_array()
if (options.filter_file)
  require options.filter_file
  array_that_might_get_filtered = FILTER.do_filter(array_that_might_get_filtered)
end

虽然这可行,但感觉很俗气,似乎应该有更好的方法来做到这一点。我还考虑让过滤器采用将已知名称的方法添加到已知类的形式,但这似乎也不太正确。

Ruby中有更好的成语吗?

4

3 回答 3

4

我只是使用命令行和约定的组合。

如果指定了过滤器,则使用它来过滤数据

我假设您会在命令行上指定一个过滤器?所以你会像这样调用应用程序?

ruby dataprocessor.rb custom_filter

如果是这样,您可以定义一个“api”,其中类名必须与传入的内容相匹配 - 几乎与您在示例中所描述的完全一样。

不过,为了更进一步,您可以使用一些逻辑来查找CustomFilter使用 ruby​​'s 的类defined?,如果找不到,请查找custom_filter.rb(或任何合适的变体)并尝试加载该文件,然后重试。

这为您提供了极大的可扩展性,因为您可以编写任意数量的过滤器类,将它们放入自己的 .rb 文件中,并将它们放在 ruby​​ 可以找到它们的任何地方。您也不必有预定义的常量,唯一的约束是

  1. 类名必须匹配文件名(的变体)——这是 ruby​​ 中的约定,所以你可能已经在这样做了。
  2. 它必须有一些预定义的方法,比如你的do_filter方法

顺便说一句,这与 rails 需要您的模型所做的非常相似,这就是为什么您可以直接使用SomeModel而不必总是先做require app/models/some_model:-)`

于 2008-10-30T20:19:20.253 回答
0

看起来像是Strategy Pattern的工作,并且由于 ruby​​ 具有作为第一类对象的功能,您可以传递过滤器函数以由数组存储,以便按需调用该自定义过滤器函数。

于 2008-10-30T19:50:52.383 回答
0
# user code
USER_FILTER = lambda { |value| value != 0xDEADBEEF }

# script code
load( user_code );
FILTER = ( const_defined?(:USER_FILTER) ? USER_FILTER : lambda { true } )

output_array = input_array.filter(&FILTER)
于 2008-10-30T20:28:23.837 回答