2008-10-30 12 views
6

Tengo una aplicación de línea de comandos de Ruby que estoy desarrollando y quiero permitir que un usuario de ella proporcione código que se ejecutará como un filtro en parte del proceso. Básicamente, la aplicación hace lo siguiente:Script de una aplicación de línea de comandos de ruby; la mejor manera de hacer esto?

  1. de lectura en algunos datos
  2. Si se especifica un filtro, lo utilizan para filtrar los datos
  3. proceso de los datos

Quiero que el proceso de filtración (paso 2) ser lo más flexible posible.

Mi idea era que el usuario podría proporcionar un archivo de Ruby que establece una constante conocida para apuntar a un objeto que implementa una interfaz defino, por ejemplo:

# 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 

código de mi aplicación sería entonces hacer algo como esto:

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 

Mientras que esto funcionaría, se siente cursi y parece que debe haber una mejor manera de hacerlo. También consideré tener el filtro en la forma de agregar un método de un nombre conocido a una clase conocida, pero tampoco me pareció del todo correcto.

¿Hay una mejor expresión idiomática en Ruby para esto?

Respuesta

4

Solo usaría una combinación de la línea de comandos y la convención.

Si se especifica un filtro, lo utilizan para filtrar los datos

Asumo que le especifica un filtro en la línea de comandos? Entonces invocarías la aplicación de esta manera?

ruby dataprocessor.rb custom_filter 

Si es así, se podría definir un "API" en el que un nombre de clase tendría que coincidir con lo que se aprobó en - casi exactamente la forma en que has descrito en tu ejemplo.

Para dar un paso más allá, sin embargo, usted podría tener cierta lógica, que buscó la clase CustomFilter usando rubí de defined?, y si no se encuentra, ir a buscar a custom_filter.rb (o cualquier variación adecuados) y el intento de cargar ese archivo , luego vuelve a intentarlo.

Esto le proporciona gran capacidad de ampliación, ya que puede escribir tantas clases de filtro como desee, colocarlas en sus propios archivos .rb y colocarlas en cualquier lugar donde Ruby pueda encontrarlas. Usted no tiene que tener una constantes predefinidas o bien, las únicas limitaciones serán

  1. El nombre de la clase debe coincidir (una variante de) el nombre del archivo - Esta es la convención en Ruby por lo que es probable que ya haciéndolo de todos modos.
  2. debe tener algún método predefinido, tal como su do_filter método

Por cierto, este es bastante similar a lo que los carriles hace para exigir a sus modelos, y es por eso que sólo puede utilizar SomeModel sin tener que hacer siempre require app/models/some_model primero :-) `

+0

Mucho más práctico que mi respuesta general. +1 – VonC

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) 
Cuestiones relacionadas