I’m usually reluctant to go change “big things”, almost always preferring to work around any issues I encounter. On the rare occasion though, I find I really must make changes or I’d forget what I did and struggle with it again later.
The script/plugin install command in Rails is a wonderful thing. It fetches code from repositories (like subversion or github) and installs it into your Rails application. Plugins generally extend Rails’ capabilities, much in the way that Ruby is extended through Rubygems. However, the plugin installer assumes a repository, or at least the web. If there is a local copy of the plugin in your environment that you’d like to use as the source, you’re out of luck. You have to do the install by hand, and remember to set up some environment specification. There’s just no provision for local installs.
Necessity being the mother of invention, when I found myself needing to install a plugin from local sources, I tried to find a workaround. When I could find nothing satisfying, I did some editing. A very slight amount of editing.
In ruby/lib/ruby/gems/1.8/gems/rails-2.1.0/lib/commands/plugin.rb
class Plugin
# test for local
def file_url?
@uri =~ /^\//
end
def install(method=nil, options = {})
method ||= rails_env.best_install_method?
if :http == method
method = :export if svn_url?
method = :clone if git_url?
# if it's local...
method = :file if file_url?
end
uninstall if installed? and options[:force]
unless installed?
send("install_using_#{method}", options)
run_install_hook
else
puts "already installed: #{name} (#{uri}). pass --force to reinstall"
end
end
private
# install local
def install_using_file(options = {})
root = rails_env.root
mkdir_p "#{root}/vendor/plugins"
Dir.chdir "#{root}/vendor/plugins" do
cp_r @uri, @name
end
end
end
That is, if the specified plugin being installed starts with a slash, assume it’s an absolute path to the directory that contains the plugin and fetch it by copying. Then the install can go along it’s merry way.
Now I can just fire off a
$ ruby script/plugin install /Downloads/rails/plugins/foo
and it will install the foo
plugin in the specified directory into my Rails project, just as if it were out on the net.
This certainly may not be perfect, and if I were polishing it I’d add a check for a file:
protocol and include relative paths, but this was just enough for my needs.