I'm making a gem for internal use. In it, I load some YAML from another directory:
# in <project_root>/bin/magicwand
MagicWand::Configuration::Initializer.new(...)
# in <project_root>/lib/magicwand/configuration/initializer.rb
root_yaml = YAML.load_file(
File.expand_path("../../../../data/#{RootFileName}", __FILE__))
# in <project_root>/data/root.yaml
---
apple: 100
banana: 200
coconut: 300
I'd rather not depend on the location of data/root.yaml relative to initializer.rb. Instead, I'd rather get a reference to <project_root> and depend on the relative path from there, which seems like a smarter move.
First, is that the best way to go about this? Second, if so, how do I do that? I checked out the various File methods, but I don't think there's anything like that. I'm using Ruby 1.9.
Right now, I create a special constant and depend on that instead:
# in lib/magicwand/magicwand.rb
module MagicWand
# Project root directory.
ROOT = File.expand_path("../..", __FILE__)
end
but I'm not sure I like that approach either.
If there's a main file you always run you can use that file as a reference point. The relative path (between the current directory and) of that file will be in $0, so to get the relative path to data/root.yaml (assuming that is the relative path between the main file and root.yaml) you do
path_to_root_yaml = File.dirname($0) + '/data/root.yaml'
Related
My project structure looks like this:
Project_root
|__Templates
| |__Report_Template
|
|__Product
|__product.rb
What code should I write in product.rb in order to copy Report_Template folder and its content into Product folder?
I tried to use FileUtils.cp_r, but then I will have to give full path of source folder and if in a future I move Project_root, there will be issues.
As Kenney says, you can get the path from which the program started, in __dir__. Here I use Pathname class for easier path manipulation, but it is entirely optional (you can use File#join etc. just as well):
require 'pathname'
templates_pathname = Pathname.new(__dir__) + "../Templates/Report_Template"
# optional:
templates_path = templates_pathname.realpath.to_s
Pathname#realpath will give you the absolute path, if you need it; but FileUtils#cp_r will happily accept a Pathname (i.e. templates_pathname above), and won't mind it's not absolute.
Suppose file_a and file_b live in the same directory, and file_a contains a require statement that requires file_b. The way to do this seems to be like so:
require File.expand_path('../file_b', __FILE__)
But kind of expected it to look like this instead:
require File.expand_path('./file_a', __FILE__)
I played around with it and sure enough, the ./ version doesn't work and the ../ version does. The ./ version returns a path like path/to/file_a/file_b. Is the concept that code inside file_a lives inside that file, much like file_a "lives" inside it's parent directory? I feel like I just answered my own question, but want to make sure I'm understanding this right.
File.expand_path(file_name [, dir_string] ) -> abs_file_name
Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless dir_string is given, in which case it will be used as the starting point.
File.expand_path treats the second (optional) parameter as dir_string, it doesn't care whether it is actually a directory or not. So it's your job to make sure the second parameter passed in be a path to a directory.
If you want preserve the ./file_a part, you may change the second parameter passed in:
require File.expand_path('./file_a', File.dirname(__FILE__))
So I'm making a game with Ruby/Gosu and the lines to load all the images look like this:
#image_name = Gosu::Image.new(self, 'C:\Users\Carlos\Desktop\gamefolder\assets\bg.jpg', false)
I want to refer to them based on their location relative to the referring file. The file which includes the above line is in C:\Users\Carlos\Desktop\gamefolder\, so I would think I could just change the above to '\assets\bg.jpg' or 'assets\bg.jpg', but this doesn't work.
The specific error is "Could not load image assets/bg.jpg using either GDI+ or FreeImage: Unknown Error (Runtime Error)."
If you want to get the current directory (of your execution context, not necessarily the file you're 'in'), just use Dir.pwd. Output this to console to check that your current directory is actually gamefolder.
To get the current directory of your actual ruby file (relative to Dir.pwd), use __FILE__, e.g.
File.dirname(__FILE__)
Pass that to File.expand_path to get a fully-qualified path. You can do a little sanity check by making sure File.exists?("#{File.expand_path File.dirname __FILE__}/assets/bg.jpg") returns true.
(Try File.expand_path('assets/bg.jpg')...that might be all you need here.)
So I want to make a file path relative to the directory it is in, in Ruby.
I have a project, and I want it to be able to find the file no matter what directory the project is unzipped into. (Say the code is run on different machines, for example) I can't figure it out for the life of me.
It seems for requires that I can do this:
require File.dirname(__FILE__) + '/comparison'
What can I do for a file that is in a different directory than my src folder?
Instead of listing,
file = 'C:/whole path/long/very_long/file.txt'
I'd like to say:
file = 'file.txt'
or
file = File.helpful_method + 'file.txt'
file = File.join(File.dirname(__FILE__), '..', 'another_dir', 'file.txt')
Replace '..', 'another_dir' with the relative path segments that reach 'file.txt'.
If you're running Ruby 1.9.2 or later, you can use require_relative instead:
require_relative '../somewhere/file.rb'
This doesn't solve the general problem of referring to files by their relative path, but if all you're doing is requiring the file, it should work.
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.