views:

388

answers:

3

I'm working on an engine for Rails as a plugin. I'd like it to be able to make necessary changes to Rails' configuration when it's loaded so it can specify its Gem dependencies as well as add some load paths.

The plugin's init.rb file has access to the config object but this is effectively read-only, you can specify a gem but it makes no difference, the initializer must have run already at this point.

I've got around this for now by requiring a file with a new Rails::Initializer block like so:

Rails::Initializer.run do |config|
  config.gem "authlogic", :version => ">= 2.0.9"
  # etc
end

This works but wipes out any existing configuration in the main application's environment.rb.

Maybe I can solve this by having a generator in the engine that adds something to environment.rb that loads the plugin's config at the right stage, or maybe there is a way of adding a file to config/initializers to do this job. Not sure how best to go about this though.

+1  A: 

I would go with the config/initializers route. That is the standard folder to put plugin-specific config code and it will get loaded at the correct time.

For implementation, I would try my hardest to choose sensible defaults for everything that allowed me to not have a config file. (I understand this is not always possible.)

Next I would create a generator with the plugin that would automatically create the config file in config/initializers using:

./script/generate plugin MyPlugin --with-generator

Finally, I would put something in install.rb of my plugin to run the generator script when the plugin is installed. This way the config file is generated automatically with the install, and the user still has an easy way to regenerate if he wants to restore the default configuration.

erik
That sounds like a good approach to me.Unlike the config files in environments (development.rb etc.) files in config/initializers don't have access to the config object, do you happen to know how I would specify the gem dependencies in this situation?Thanks
DavidNorth
So far the only way I can figure out to do this is to load a file from my engine as a string and eval it from within the Rails::Initializer block in environment.rb so that file will have access to 'config' and be able to call config.gem eval( File.read("#{RAILS_ROOT}/vendor/plugins/my-engine/config/gems.rb") )This is very ugly but it seems like you don't get to specify gem dependencies outside of that block.I suppose my generator could just add the relevant lines within that block but I'd like to keep the engine's requirements as separate as possible.
DavidNorth
A: 

You can easily add this line to init.rb (under your plugin directory) config.gem 'quick_magick' I tried it with rails 2.3.5 and it worked like magic.

Ahmed ElDawy
A: 

Are you sure you want to distribute this as a plugin rather than a gem? If you package your engine as a gem then you can specify gem dependencies as part of your gem build process. For example, if you use Jeweler to create your gem you just add a single line:

s.add_dependency 'authlogic'

When your gem is installed it will make sure all dependencies are installed. Google 'jeweler gem dependency' for a full Jeweler config example.

Also, I've been doing a lot of work on my own rails engine and recently extracted a lot of useful base functionality. You may find this helpful for other engine issues:

http://keithschacht.com/creating-a-rails-3-engine-plugin-gem/

Keith Schacht