Having your plugins and eating them too...
Liquid error: undefined method `login' for nil:NilClass : June 11th, 2006
Let's face it, rails plugins are a great way of making rails uniquely your own. And since full blown components are going the way of the dodo, wouldn't it be nice to be able to use controllers, models, views and helpers in a plugin without any other dependencies? Well after spending a bunch of time trying to figure out how to do it, it turns out its only 4 lines of code.
Now this won't let you over-ride things in your main app or any other snazzy stuff like that. But I don't need that,. I just want to have a little mvc stack in my plugins sometimes.
So for this to work, just add these four lines into the init.rb of a fresh plugin.
config.controller_paths << File.join(directory, 'app', 'controllers') $LOAD_PATH << File.join(directory, 'app', 'controllers') $LOAD_PATH << File.join(directory, 'app', 'models') $LOAD_PATH << File.join(directory, 'app', 'helpers')Then you can make an app/ directory in the root dir of the plugin with a directory for controllers, helpers, models and views inside. The way this works is that the config and directory local variables are automatically available to any plugin. The config var is the same as the Rails::Initializer.run do |config| block inside environment.rb in your main app. This just allows you to tack on more config stuff from a plugin. And the directory var is available and points to the root directory of your plugin. So we are just puting out little app/ dir into the load path in the proper way and it just works. I also usually make a symlink inside public in my main app that points to a dir in my plugin so I can have images and assetts. Also you need to add one line to the bottom of each of your controllers in order to set their template root. So if you have a FooController you need to put the following line after the class definition:
FooController.template_root = File.join(File.dirname(__FILE__), '..', 'views')
18 Responses to “Having your plugins and eating them too...”
Sorry, comments are closed for this article.
June 11th, 2006 at 09:18 PM Nice work! It's worth pointing out that this isn't quite the same as the functionality that components have/had (which closer to partials with dedicated controller logic than an MVC stack), but still, this is definitely neat. And who needs components anyway? :) One other minor thing to consider is that adding paths to the top of $LOAD_PATH might make your development mocks harder to load. You could try some variation of this instead, if you had any issues:
# add the paths after /components index = $LOAD_PATH.index($LOAD_PATH.find { |p| p =~ /\/components$/ }) + 1 $LOAD_PATH.insert(index, *%w{controllers models helpers}.collect { |d| File.join(directory, 'app', d) })June 12th, 2006 at 01:01 AM Awesome! But how can I setup a route from the plugin?
June 15th, 2006 at 08:41 AM Ezra rocks!
June 16th, 2006 at 12:40 AM Woah... wait, let's coin a term for doing this... like... Engines. Rawk.
May 17th, 2007 at 03:34 AM
Sorry :(
May 17th, 2007 at 07:42 AM
Nice
May 17th, 2007 at 08:32 AM
Nice…
May 18th, 2007 at 08:42 PM
Nice!
June 18th, 2007 at 05:45 PM
Cool…
June 24th, 2007 at 12:08 PM
Cool!
July 9th, 2007 at 04:41 AM
Sorry :(
July 9th, 2007 at 07:32 AM
Cool.
July 9th, 2007 at 10:34 PM
Sorry :(
July 10th, 2007 at 01:22 AM
Interesting…
July 10th, 2007 at 02:28 AM
Cool.
July 10th, 2007 at 06:24 AM
Interesting…
July 10th, 2007 at 12:57 PM
Nice!
July 10th, 2007 at 04:17 PM
Cool!