I want to execute some code at pre install time when installing a gem from rubygems.org with a command like gem install some-gem
.
The documentation states that you can use a http://docs.ruby-lang.org/en/2.2.0/Gem.html pre_install hook that looks like this:
# File lib/rubygems.rb, line 724
def self.pre_install(&hook)
@pre_install_hooks << hook
end
The doc further states:
RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging RubyGems or implementing Ruby you can change RubyGems' defaults. For RubyGems packagers, provide lib/rubygems/defaults/operating_system.rb and override any defaults from lib/rubygems/defaults.rb. For Ruby implementers, provide lib/rubygems/defaults/#{RUBY_ENGINE}.rb and override any defaults from lib/rubygems/defaults.rb. If you need RubyGems to perform extra work on install or uninstall, your defaults override file can set pre and post install and uninstall hooks. See ::pre_install, ::pre_uninstall, ::post_install, ::post_uninstall.
This sounds exactly what I want. So I created the files
and I put the code
Gem.pre_install { puts 'pre install hook called!' }
in all of the listed files. Then I added them to require_paths in the gemspec like this:
s.require_paths = ["lib", "test", "rubygems"]
But I see no output in the terminal when installing the gem.
What am I doing wrong?
There are several ways to specify gem versions: Use a specific version: gem "name-of-gem", "1.0" . You can find specific versions on Rubygems.org (provided that's the source you”re using) by searching for your gem and looking at the “Versions” listed. Use a version operator: gem "name-of-gem", ">1.0" .
Using gem search -r , you can search RubyGems' repository. For instance, gem search -r rails will return a list of Rails-related gems. With the --local ( -l ) option, you would perform a local search through your installed gems.
A Gemfile is a file that is created to describe the gem dependencies required to run a Ruby program. A Gemfile should always be placed in the root of the project directory.
Gemspec is the Readme for gems. It tells you about the author, version, summary, description, internal dependencies, execution - pretty much everything about the gem. You can find more useful information about these topics here.
You can add a native extension to the gem.
gemspec: s.extensions << 'path/to/extconf.rb'
But then the gem install
command want to execute a Makefile upon installation.
So the extconf.rb
must create a dummy Makefile:
dummy_make_content = "make:\n" \
"\t:\n" \
"install:\n" \
"\t:\n" \
"clean:\n" \
"\t:\n"
File.write('Makefile', dummy_make_content)
Alternatively you can require the mkmf package and use a predefined function:
require 'mkmf'
create_makefile ''
The answer is presently (2015-11-11) NO you cannot execute arbitrary code at install time for a specific gem. The hooks mentioned in your question are for use by the RubyGem installer itself and are not gem specific. See: How can I make a Ruby gem package copy files to arbitrary locations? for additional details.
These files:
lib/rubygems/defaults/defaults.rb
lib/rubygems/defaults/operating_system.rb
rubygems/defaults.rb
Are not called from your gem directory. They are found in the RubyGems system location.
If you wish to execute the same code for every gem before any are installed then you can use the pre_install hooks by placing the code in /usr/lib64/ruby/2.2.0/rubygems/defaults.rb
or wherever your version of Ruby is installed on your system. The operating_system.rb
file will get loaded from the same location as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With