Finding the gem root
Given the following project structure:
your_gem/
lib/
your_gem.rb
Here's how I would do it:
# your_gem.rb
module YourGem
def self.root
File.expand_path '../..', __FILE__
end
end
Ruby 2.0 introduced the Kernel#__dir__
method; it enables a considerably shorter solution:
# your_gem.rb
module YourGem
def self.root
File.dirname __dir__
end
end
If you need access to the other directories, you can simply build upon root
:
module YourGem
def self.bin
File.join root, 'bin'
end
def self.lib
File.join root, 'lib'
end
end
Get Ruby project root path from a Gem
Check out this forum: https://www.ruby-forum.com/topic/143383
From my understanding of your question, you want to get the path of the project NOT the path of where the gem itself is located.
class MyGem
def self.get_working_dir
Dir.pwd
end
end
> MyGem.get_working_dir
> /Users/your_name/my_project_directory
This solution ended up helping out a Gem I had made where I had to iterate through a project's file tree.
From a Ruby Gem, how can I get the directory path to the project?
There is no perfect solution to this problem but you could create a fallback based solution that would work in most general cases. If Rails is defined, we use Rails.root
. If Bundler is defined, we use the Bundler.root
but it would only work when the Gemfile is defined at the project root (which is true in most cases). Else fallback to Dir.pwd
def project_root
if defined?(Rails)
return Rails.root
end
if defined?(Bundler)
return Bundler.root
end
Dir.pwd
end
How to find where gem files are installed
Use gem environment
to find out about your gem environment:
RubyGems Environment:
- RUBYGEMS VERSION: 2.1.5
- RUBY VERSION: 2.0.0 (2013-06-27 patchlevel 247) [x86_64-darwin12.4.0]
- INSTALLATION DIRECTORY: /Users/ttm/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0
- RUBY EXECUTABLE: /Users/ttm/.rbenv/versions/2.0.0-p247/bin/ruby
- EXECUTABLE DIRECTORY: /Users/ttm/.rbenv/versions/2.0.0-p247/bin
- SPEC CACHE DIRECTORY: /Users/ttm/.gem/specs
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-darwin-12
- GEM PATHS:
- /Users/ttm/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0
- /Users/ttm/.gem/ruby/2.0.0
- GEM CONFIGURATION:
- :update_sources => true
- :verbose => true
- :backtrace => false
- :bulk_threshold => 1000
- REMOTE SOURCES:
- https://rubygems.org/
- SHELL PATH:
- /Users/ttm/.rbenv/versions/2.0.0-p247/bin
- /Users/ttm/.rbenv/libexec
- /Users/ttm/.rbenv/plugins/ruby-build/bin
- /Users/ttm/perl5/perlbrew/bin
- /Users/ttm/perl5/perlbrew/perls/perl-5.18.1/bin
- /Users/ttm/.pyenv/shims
- /Users/ttm/.pyenv/bin
- /Users/ttm/.rbenv/shims
- /Users/ttm/.rbenv/bin
- /Users/ttm/bin
- /usr/local/mysql-5.6.12-osx10.7-x86_64/bin
- /Users/ttm/libsmi/bin
- /usr/local/bin
- /usr/bin
- /bin
- /usr/sbin
- /sbin
- /usr/local/bin
Notice the two sections for:
INSTALLATION DIRECTORY
GEM PATHS
How do I find the location of the gem?
You can always make use of the backtrace facility provided:
caller.first
It produces an amalgam of file and line but is usually separated by :
. I'd be careful to allow for filenames or paths that may contain colon for whatever reason by ignoring the line information but preserving the rest. In other words, do not split
but sub
:
caller.first.sub(/:\d+:in .*$/, '')
Find root of project from included gem
Most modern gems don't look for a particular config file. Instead, they expect a config file of any name to be executed, which will set configurations via a .config
variable on the gem's class name. For example, I might have this config file:
# config/initializers/ams.rb
ActiveModelSerializers.config.adapter = :json_api
ActiveModelSerializers.config.key_transform = :camel_lower
Now it doesn't matter where the file is located or what it's called. So long as the code is executed, ActiveModelSerializers can look at its own ActiveModelSerializers.config
variable and it is good to go.
If you wanted an extensive configuration (by means of a .yml file, for example) you might create a .config.path
setting and instruct users of your gem to set the path themselves and then create a file in the spot they choose:
# config/initializers/gem_b.rb
GemB.config.path = '/config/gem_b.yml'
How do I get the root directory of a Rails app in a Gem
The solution that I found to fix a similar problem to this is to include my module using the railtie initializers.
So, in your /lib/mygem/railtie.rb
module MyGem
class Railtie < Rails::Railtie
initializer "Include your code in the controller" do
ActiveSupport.on_load(:action_controller) do
include MyGem
end
end
end
With this code, your module will be included after the ActionController is loaded and you will be able to use Rails.root
Let me know if this works for you.
Related Topics
Installing Libyaml for Ruby on a MAC Osx (Lion)
How to Reference a Method in Another Ruby Code File
Rails Render of Partial and Layout in Controller
How to Connect to Browser Using Ruby Selenium Webdriver
Rvm System-Wide Install Script Url Broken -- What Is Replacement
How to Use Escape Characters in Strings
Rails: How to Print a Decimal as a Percent
Find Where Associated Records Exist
Rails 4.0.3 Generating Incorrect Asset Paths with Asset_Sync
Ruby on Rails: Search Form - Multiple Search Fields
Actioncable - Failed to Upgrade to Websocket in Production
Ruby: Differencebetween the Comparatives: "||" and "Or"
Rbenv Installed Ruby 2.1.2 Cannot Load Such File -- Zlib on MAC Osx 10.9.2
Rails 4: How to Upload Files with Ajax
Ruby: What Is the Order of Keys/Values Returned by Hash.Keys and Hash.Values Methods