Script ruby ​​command line application; best way to do this?

I have a Ruby command-line application that I am developing, and I want to allow the user to provide it with code that will work as a filter on part of the process. Basically, the application does this:

  • reading some data
  • If a filter is specified, use it to filter data.
  • process data

I want the filtering process (step 2) to be as flexible as possible.

I thought the user could provide a Ruby file that sets a known constant, pointing to an object that implements the interface that I define, for example:

# user 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 

My application code will then do something like this:

 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 

While this works, it seems crappy, and it seems like there should be a better way to do it. I also thought that the filter should be in the form of adding a known name method to a known class, but this also did not seem to be correct.

Is there a better idiom in Ruby for this?

+6
idioms ruby
source share
3 answers

I would just use a combination of command line and convention.

If a filter is specified, use it to filter data.

I assume that you specify a filter on the command line? So, you invoke the application as follows?

 ruby dataprocessor.rb custom_filter 

If so, you can define an “api” in which the class name should match what was passed in, just like you described in your example.

To take this one step further, could you have some logic that the CustomFilter class was looking for using ruby ​​defined defined? , and if it was not found, look for custom_filter.rb (or any suitable options) and try downloading this file, and then try again.

This gives you great extensibility, since you can write as many filter classes as you want, drop them in your .rb files and put them where you can find them in ruby. You also do not have to have predefined constants, the only restrictions will be

  • The class name must match the file name. This is an agreement in ruby, so you probably already do all this.
  • it must have some predefined method, for example do_filter method

By the way, this is very similar to what rails do for your models, and so you can just use SomeModel without always SomeModel require app/models/some_model first :-) `

+4
source share

It looks like it works for Strategy Pattern , and since ruby ​​has both first-class objects , you can pass a filter function that will be remembered by an array to call a custom filter function on demand.

0
source share
 # 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) 
0
source share

All Articles