tl;dr; Kernel#enum_for lets you treat your method like a collection.
I was iterating over the files in a folder, looking for those with a specific file extension. I had something like this...
Now I'm sure Ruby provides a better way to achieve this, but it worked for me... until I found I was filtering this list again in the block I was passing in.
What I wanted was something like this:
Well as per usual Ruby 2.0 has already thought of that.
Note the
Also.. I think this means I can also make it lazy like this...
Nice!
Update:
On a similar theme I was wrapping up a COM API that has iterators using
def for_all_files(f, e, &block)
Dir[f+"/*"].each { |file|
if(File.directory?(file))
for_all_files(file, e, &block)
else
block.call(file) if file.end_with?(e)
end
}
end
Now I'm sure Ruby provides a better way to achieve this, but it worked for me... until I found I was filtering this list again in the block I was passing in.
for_all_files(source_folder, ".ts") do |file|
if(path_filter =~ file)
...
end
end
What I wanted was something like this:
files(source_folder, ".ts").
select{|file| path_filter =~ file}.each do |file|
...
end
Well as per usual Ruby 2.0 has already thought of that.
def files(folder, ending)
def for_all_files(f, e, &block)
Dir[f+"/*"].each { |file|
if(File.directory?(file))
for_all_files(file, e, &block)
else
block.call(file) if file.end_with?(e)
end
}
end
enum_for(:for_all_files, folder, ending)
end
Note the
enum_for. It takes a symbol for a method name and a set of arguments. It returns an Enumerable that encapsulates your method. I really like the result of this but I don't like the code. If you know a better way, let me know. Post a comment telling me how I should have written it.Also.. I think this means I can also make it lazy like this...
files(source_folder, ".ts").
lazy.
select{|file| path_filter =~ file}.
each do |file|
...
end
Nice!
Update:
On a similar theme I was wrapping up a COM API that has iterators using
Count and Child(x) methods. With Enumerator.new you can easily wrap these to expose a clean ruby API.
def child_folders(folder)
Enumerator.new do |y|
(1..folder.Count).each {|i| y << folder.Child(i)}
end
end
No comments:
Post a Comment