Tuesday, September 23, 2008

Installing Rails Plugins from Local Sources

I'm usually reluctant to go change "big things", almost always prefering to work around any issues I encounter. On the rare occaision 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
  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?
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
    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.

4 comments:

darrowj said...

Thank you kind Sir!

I did this and it worked out great. For some odd reason I was not able to get a plugin via git or http. Downloading and installing source locally is now an option! And why not :-)

Best Regards,
Jason Darrow

NWILD said...

Thank you! Thank you!

I was unable to do a remote git install for geo-kit but was able to clone the repository no problem. Best of all ./script/plugin install produced no output of any kind. Everything worked like a charm locally after making these changes and using the locally cloned source.

Please consider submitting this very helpful change to the rails team. Your work could help many others!

arty said...

Thanks alot, that was of greate use for me as writing-plugins-starter. Absolutely agreed with previous poster, this useful code change must be included in rails.

Best regards, rt.

agus said...

I trying installing the new version with RVM, may be this helping for all http://minimalbugs.com/questions/install-rails-3-0-3-in-ubuntu-with-help-of-rvmper