I have a command line Ruby app I'm developing and I want to allow a user of it to provide code that will run as a filter on part of the process. Basically, the application does this:
I want the filtering process (step 2) to be as flexible as possible.
My thinking was that the user could provide a Ruby file that set a known constant to point to an object implementing an interface I define, e.g.:
# 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
My app's code would 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 would work, it feels cheesy and it seems like there should be a better way to do it. I also considered having the filter be in the form of adding a method of a known name to a known class, but that didn't seem quite right, either.
Is there a better idiom in Ruby for this?
Creating a Ruby Script. Let's start by creating a "Hello World!" script in Ruby. #!/usr/bin/env ruby puts "Hello world!" We can run this script in the command line by going to the directory where the file lives and typing in ruby hello.
How to Use Command-Line Arguments. In your Ruby programs, you can access any command-line arguments passed by the shell with the ARGV special variable. ARGV is an Array variable which holds, as strings, each argument passed by the shell.
Ruby command is a free and open source programming language; it is flexible and is feature rich. As the name suggests, ruby indeed is a jewel language which comes at a very low entry cost. Its plug and play capability and also easily readable syntax makes it very user-friendly.
I'd just use a combination of the command line, and convention.
If a filter is specified, use it to filter data
I'm assuming you'd specify a filter on the command line? So you'd invoke the application like this?
ruby dataprocessor.rb custom_filter
If so, you could define an "api" wherein a class name would have to match what was passed in - pretty much exactly how you've described in your example.
To take it one step further though, you could have some logic which looked for the CustomFilter
class using ruby's defined?
, and if it was not found, go looking for custom_filter.rb
(or any suitable variations) and attempt to load that file, then retry.
This gives you great extensibility, as you can write as many filter classes as you like, chuck them in their own .rb files, and put them anywhere that ruby can find them. You won't have to have an pre-defined constants either, the only constraints will be
do_filter
methodIncidentally, this is pretty similar to what rails does for requiring your models, and is why you can just use SomeModel
without having to always do require app/models/some_model
first :-)`
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With