Nikolai Tschacher Nikolai Tschacher - 3 months ago 15
Ruby Question

How to add a (pre/post)_install_hook to ruby gems

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


  • lib/rubygems/defaults/defaults.rb

  • lib/rubygems/defaults/operating_system.rb

  • rubygems/defaults.rb



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?

Answer

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.

Comments