Rails plugins and libraries / Installing and using

From WhyNotWiki

Jump to: navigation, search

Contents

[edit] Can plugins be installed as gems (system-wide)?

[Questions (category)]

Yes!

The Plugin Dependencies plugin[1], for example, can be installed as a gem.

Installation is simple:

> sudo gem install plugin_dependencies

config/environment.rb:
require 'plugin_dependencies'
Rails::Initializer.run do |config|
  ...

With gems, you can even take advantage of gem dependencies. So instead of installing 5 plugins via Subversion (which is a pain, partly because you have to look up / remember the full URL of each plugin), you can just do a single gem install and it will automatically install the 5 plugins it depends on!

> sudo gem install plugins_plus
Bulk updating Gem source index for: http://gems.rubyforge.org
Install required dependency loaded_plugins? [Yn]
Install required dependency appable_plugins? [Yn]
Install required dependency plugin_routing? [Yn]
Install required dependency plugin_assets? [Yn]
Install required dependency plugin_migrations? [Yn]

[edit] Efforts to include gem plugin loading into core Rails

The fact that the above examples are possible is, I believe, unrelated to any special code within the Rails system to deal with gem plugins. In other words, I guess this has been possible all along, but few people actually released plugins as gems.

But it does require adding a "require" at the top of your config/environment.rb, before the Initializer is even run. And that's not very Rails-y.

Ticket #6726 ([PATCH] Add support for RubyGem-based plugins) in the Rails tracker, however, plans to change that. It would add support so that you can specify gem-based plugins in your config.plugins array:

    config.plugins = ['foo', 'bar', 'baz', ['spam', '>0.9.0', '<=1.2.3'], 'eggs']

I, however, question the value of this ticket to people like me who would rather not use config.plugins in the first place, if possible, because it requires you to list out all your plugins...

Oh well, I'll keep watching this and see what comes of it...

http://dev.rubyonrails.org/ticket/6726

The trick with gem-based plugins is the fact that you might have many gem plugins installed, but might only want to use a small subset for any given application-- hence the use of config.plugins. Obviously using config.plugins is restrictive-- since if you are using "normal" path-based plugins you have to include them in the list for them to be enabled, but it is elective (and I consider the dependency-resolution mechanism that RubyGems offers well worth maintaining a config.plugins list).

As to how it works: Gems are loaded, then their lib/ paths are added to load_paths and load_once_paths as with any plugin (so autoloading works as expected). init.rb is also loaded in the same way as it is with the current path-based plugins (no need to specifically set it to be autorequired by the gem)-- this is so that 'config', etc are available to the plugin.

It seems like to benefit from the "dependency-resolution mechanism that RubyGems offers", you'd have to be using all gem-based plugins... I wonder how well all this works when you have a mix of gem-based and non-gem-based plugins...

[edit] Going the other way: unpacking gems and putting them in vendor/

There's an interesting command-line tool/gem called, GemsOnRails, that seems to take the exact opposite approach of gem-based plugins: rather than turning everything (including plugins) into gems, it recommends unpacking all gems into your vendor/ directory so that you wouldn't even be using RubyGems (for those libraries that you unpack)...

"vendor everything"


Homepage: http://gemsonrails.rubyforge.org/









Link or freeze RubyGems into your rails apps, instead of just plugins. This allows you to ‘vendor everything’ – pushing all dependent gems into your rails app thus ensuring your application will be guaranteed to work when deployed. Your application is no longer dependent on the gems that are/aren’t available on your target deployment environment.

...

I actually fail to see what this has to do with Rails at all. Unpacking gems is a feature of RubyGems, not of Rails. All this plugin does (apparently) is provide some rake tasks to wrap the gem unpack command, and to enforce the convention that unpacked gems go into a vendor/gemsw subdirectory of your Rails app. Woop-de-doo.

Hmm, I guess another thing it does for Rails is auto-requires the library-that-was-formerly-a-gem-but-is-now-unpacked-under-vendor during app initialization. That's kind of handy. But still not very compelling. (It's not hard to add a require line to environment.rb...)

I'm not sure what this task actually does:

rake gems:link      # Link a RubyGem into this Rails application; init.rb will be loaded on startup.

What is this "linking" you speak of, Dr. Nic?

The possibility of unpacking gems for the purpose of "ensuring your application will be guaranteed to work when deployed" is one I have considered before (see Gems or svn:externals?), and I'm still not sure what the best solution is.

If I ever did decide that unpacking gems was the best way to go, then I'd definitely want to give GemsOnRails a second look...

[edit] Specifying load order

[Problem (category)]: Sometimes your plugins need to be loaded in a specific order, due to dependencies. The plugin_dependencies plugin helps with that, but still only if it is loaded first (before the plugins that use it).

[Solution (category)]: The Plugin Dependencies plugin[2]

Problem: If you have plugins that require the plugin_dependencies plugin, then you have to (unless the plugin happens to be alphabetically later than 'p') use the config.plugins = directive in your environment.rb and explicitly list out all the plugins you want to be loaded. The problem with that: You're duplicating the list of plugins that already exists in the file system as the list of entries in vendor/plugins.

Solution:

Rather than list out all your plugins...

  config.plugins = %W( plugin_dependencies annotate_models appable_plugins loaded_plugins ... )

You only need to explicitly the ones you want required first. Then you can say "then load the rest of the plugins using the default order" and it will...

  config.plugins = ['plugin_dependencies'] + Dir.new('vendor/plugins').entries.reject {|f| f =~ /^\./}

I've also heard that it's possible to use "*" to do the same thing (tell it to load "the rest of the plugins"):

  config.plugins = %W( plugin_dependencies * )

, but that didn't work for me with my version of Rails. I can't remember if they said it was available in edge Rails or with a certain plugin or what...

[edit] [Troubleshooting (category)] ./script/plugin install prompts you for a password

Example:

> ./script/plugin install whatever
Authentication realm: <svn://delynnberry.com:3690> DeLynn's Code Repository
Password for 'tyler':

Since you probably don't have a valid login to their repository (and never will), your available options are probably just one: "unsource" the offending plugin source.

First, you need to figure out the exact spelling of the source to remove:

> ./script/plugin sources | grep delynnberry.com
svn://delynnberry.com/code/plugins/

Then simply unsource it:

> ./script/plugin unsource svn://delynnberry.com/code/plugins/
removed: svn://delynnberry.com/code/plugins/
Removed 1 repositories.
Personal tools