rake - how does the "directory" keyword work? - ruby

It's been stated in several places that "directory" keyword can be used as a shorthand. Apparently, it can be indicated as a dependency, so that it will be created if not already present.
http://onestepback.org/articles/buildingwithrake/directorydependencies.html
The idea is to specify destination directory as a dependency, not to attempt to create it manually each time, which can be achieved by using mkdir_p. Downside of using mkdir_p is that it displays output regardless of whether the directory was already present. An alternative solution is to silence this command -- and even better if the output is displayed only when the directory is created.
I've tried using "directory" keyword as follows:
file "destFile" => ["srcFile", directory "myOutputDir"] do
FileUtils.cp "srcFile" "myOutputDir/destFile"
end
file "destFile" => ["srcFile"] + [directory "myOutputDir"] do
FileUtils.cp "srcFile" "myOutputDir/destFile"
end
file "destFile" => ["srcFile"] do
directory "myOutputDir"
FileUtils.cp "srcFile" "myOutputDir/destFile"
end

How about this:
directory "myOutputDir"
file "myOutputDir/destFile" => ["srcFile", "myOutputDir"] do
FileUtils.cp "srcFile" "myOutputDir/destFile"
end
I believe it's supposed to be used as a separate task and specified as a dependency like any other task. It's basically the same as specifying a file task that runs mkdir, but the action is implicit. The syntax is otherwise the same.
directory will also make all layers of subdirectories like so: http://onestepback.org/articles/buildingwithrake/directorydependencies.html

Related

Ruby FileUtils.mkdir_p is only creating parent directories

I have a controller in Rails, with an action that is meant to create a new directory.
This action should create the directory "/public/graph_templates/aaa/test". However, it leaves off the final directory "test". Why is this only creating parent directories?
def create_temporary_template
dir = File.dirname("#{Rails.root}/public/graph_templates/aaa/test")
FileUtils.mkdir_p dir
end
Docs: http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html#method-c-mkdir_p
Because you use dir = File.dirname("#{Rails.root}/public/graph_templates/aaa/test"),
then the dir is "#{Rails.root}/public/graph_templates/aaa".
You could just pass the path to FileUtils.mkdir_p.
def create_temporary_template
dir = "#{Rails.root}/public/graph_templates/aaa/test"
FileUtils.mkdir_p dir
end
The problem is in your use of dirname:
File.dirname("/foo/bar")
# => "/foo"
dirname removes the last entry from the path. Per the documentation:
Returns all components of the filename given in file_name except the last one.
Usually that's the correct thing if your path contains a directory, or directory hierarchy, with the filename:
File.dirname("/foo/bar/baz.txt")
# => "/foo/bar"
But, in this case it's chopping off your desired trailing directory.
I'd recommend taking a look at the Pathname class that is included in Ruby's Standard Library. It wraps File, Dir, FileUtils, FileTest, and probably a Swiss-Army knife and kitchen sink into one class, making it very convenient to work on files and directories with one class.
require 'pathname'
dir = Pathname.new("/foo/bar/baz.txt")
# => "/foo/bar"
dir.mkpath # would create the path
I've found Pathname to be very useful, though it's still young.

Wildcard file requires in Ruby

As an example:
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
This is how RSpec requires all of the ruby files in the support directory and all subdirectories. I know this has to do with "/**/*". What does this mean in Ruby? How does it work?
File.dirname(__FILE__) is the directory where the file is. ** and * are UNIX wildcards. Adding "/support/**/*.rb to the directory points to any file that ends with .rb, which is under an arbitrary depth under the sub-directory support under that directory.
Passing that to Dir[] gives the array of such files. each iterates over such files, and require loads each file.
i believe that the /**/ part means Any directory , and the *.rb means any file that ends with .rb extention, regardless of it's name.
so, basically, you are getting any .rb file that are in any folder in
#{current_dir}/support/#{any_dir}/#{any_file_with_extention.rb}

Buildr - exclude directory from resources

In Buildr you can exclude all files in a directory by doing the following:
resources.exclude 'scratch/*'
Is it possible to exclude the directory as well? The Buildr documentation mentions:
The filter always excludes the CVS and .svn directories, and all files
ending with .bak or ~, so no need to worry about these.
My company uses Dimensions as its source control, it creates a .metadata folder in every directory much like subversion does with the .svn folder.
These exclusions are actually inherited from Rake (rake/file_list.rb)
module Rake
...
class FileList
...
DEFAULT_IGNORE_PATTERNS = [
/(^|[\/\\])CVS([\/\\]|$)/,
/(^|[\/\\])\.svn([\/\\]|$)/,
/\.bak$/,
/~$/
]
...
end
end
so it's possible to monkey-patch the defaults, if that's what you want.
Alternatively, you can also add exclusions directly on a FileList by passing a block and calling the exclude method,
pkg_files = FileList.new('lib/**/*') do |fl|
fl.exclude(/\bCVS\b/)
end
Since Buildr filters (http://buildr.apache.org/rdoc/classes/Buildr/Filter.html) expose their underlying FileList, you can simply do:
resources.sources do |fl|
fl.exclude(/\.metadata/)
end

Directory dependencies with rake

I'm using rake to copy a directory as so:
file copied_directory => original_directory do
#copy directory
end
This works fine, except when something inside of original_directory changes. The problem is that the mod date doesn't change on the enclosing directory, so rake doesn't know to copy the directory again. Is there any way to handle this? Unfortunately my current setup does not allow me to set up individual dependencies for each individual file inside of original_directory.
You could use rsync to keep the 2 directories in sync as shown here: http://asciicasts.com/episodes/149-rails-engines
You don't need to know the files to depend on them:
file copied_directory => FileList[original_directory, original_directory + "/**/*"]

RubyZip - files from different directories have path in zip

I'm trying to use RubyZip to package up some files. At the moment I have a method which happily zips on particular directory and sub-directories.
def zip_directory(zipfile)
Dir["#{#directory_to_zip}/**/**"].reject{|f| reject_file(f)}.each do |file_path|
file_name = file_path.sub(#directory_to_zip+'/','');
zipfile.add(file_name, file_path)
end
end
However, I want to include a file from a completely different folder. I have a the following method to solve this:
def zip_additional(zipfile)
additional_files.reject{|f| reject_file(f)}.each do |file_path|
file_name = file_path.split('\\').last
zipfile.add(file_name, file_path)
end
end
While the file is added, it also copies the directory structure instead of placing the file at the root of the folder. This is really annoying and makes it more difficult to work with.
How can I get around this?
Thanks
Ben
there is setting to include (or exclude) the full path for zip libraries, check that setting
Turns out it was because the filename had the pull path in. My split didn't work as the path used a / instead of a . With the path removed from the filename it just worked.

Resources