How to Reference a File from Inside of a Gem

How to reference a file from inside of a gem

It is not clear which path you want, but probably one of the following will give you what you want:

Gem.loaded_specs["mygem"].base_dir
Gem.loaded_specs["mygem"].full_gem_path
Gem.loaded_specs["mygem"].gem_dir
Gem.loaded_specs["mygem"].gems_dir

How to tell the Gem File to use a specific local copy of a gem

Try, in your Gemfile:

gem "mygem", :path => "/MyPath/MyGem.gem"

Note that it's probably best to use a relative link in there, like:

gem "mygem", :path => "vendor/MyPath/MyGem.gem"

How does an executable within a gem reference the greater gem?

I usually add the lib dir to the library load path ($:). You can add this to the top of your bin file.

lib = File.expand_path('../../lib', __FILE__)
$:.unshift(lib) unless $:.include?(lib)

Then you can do a normal require:

require 'videoplayer'

Hope this helps.

How to reference a local gem from a ruby script?

Make sure that your gem name as same as in Gemfile (e.g. custom_gem)

# Gemfile

source "https://rubygems.org"

gem "custom_gem", path: "/home/username/path/to/custom_gem"

Don't forget to actually install this gem using bundler

bundle install

After that, the script should be ready to use by bundle exec ruby script.rb

# script.rb

require 'custom_gem'
CustomGem::Do.something

how can I go about using the Gemfile's :path argument to reference local gems in development with a value that is OS agnostic?

Use File.join('..', 'Ruby_Libs', 'my_gem'') instead of "../Ruby_Libs/my_gem".

gem "my_gem", :path => File.join('..', 'Ruby_Libs', 'my_gem'')

Opening relative paths from gem

Short answer

If I understand it correctly, you don't need to change anything.

Inside app.rb and your gem, relative paths will be understood relatively to Dir.pwd.

If you run ruby app.rb from inside /home/user/my_app :

  • Dir.pwd will be /home/user/my_app
  • both app.rb and my_gem will look for 'data.txt' inside /home/user/my_app.

Useful methods, just in case

Dir.chdir

If for some reason Dir.pwd isn't the desired folder, you could change directory :

Dir.chdir('/home/user/my_app') do
# relative paths will be based from /home/user/my_app
# call your gem from here
end

Get the directory of current file :

__dir__ will help you get the directory :

Returns the canonicalized absolute path of the directory of the file
from which this method is called.

Get the current file :

__FILE__ will return the current file. (Note : uppercase.)

Concatenate file paths :

If you need to concatenate file paths, use File.expand_path or File.join. Please don't concatenate strings.

If you don't trust that the relative path will be correctly resolved, you could send an absolute path to your method :

my_gem.load_from_file(File.expand_path('data.txt'))

How to include data files in a Ruby Gem?

Suppose you have a project structure like this:

bin/
|__ foobar*
lib/
|__ foobar/
| |__ templates/
| | |__ a/
| | |__ b/
|___|__ meta.rb
|___|__ utils.rb

In lib/foobar/teplates directory you have your template directories or
files.

lib/foobar/meta.rb file contains the name of your project and its
version. It's important to keep them (particularly a version number)
synced with the name & the version of the project in your gem
specification. (The best way to do this is read meta.rb from Rakefile
to pass values to the spec.)

For example, meta.rb may look like:

module Foobar
module Meta
NAME = 'foobar'
VERSION = '0.1.2'
end
end

Then write a function that return a full path to the lib directory
regardless whether you are testing your project from the sources
directory or the project is installed from the rubygems.

utils.rb:

require_relative 'meta'

module Foobar
module Utils

# Return a directory with the project libraries.
def self.gem_libdir
t = ["#{File.dirname(File.expand_path($0))}/../lib/#{Meta::NAME}",
"#{Gem.dir}/gems/#{Meta::NAME}-#{Meta::VERSION}/lib/#{Meta::NAME}"]
t.each {|i| return i if File.readable?(i) }
raise "both paths are invalid: #{t}"
end

# [...]
end
end

Having Foobar::Utils.gem_libdir function you can always read your
templates in bin/foobar file:

require_relative '../lib/foobar/utils'

puts Dir[Foobar::Utils.gem_libdir + '/*']
puts Foobar::Utils.gem_libdir + '/templates/a/blah-blah'


Related Topics



Leave a reply



Submit