At 37signals we usually use five or six plugins in each app. — David Heinemeier Hansson at Canada on Rails
Plugins are self-contained libraries made specially for Rails. They are a great way to reuse someone else’s code or to package your own code for reuse.
This is the first of a three part tutorial on writing plugins for Ruby on Rails.
Unlike gems, plugins are installed directly into a specific Rails app. This makes it easier to deploy them remotely along with an entire application.
I mentioned previously that the following places are good sources for plugins:
Once you’ve found a plugin that does what you want, install it into your existing Rails app like this:
# Install a plugin from a known source ./script/plugin install calendar_helper # Similar on Windows ruby script/plugin install calendar_helper # Install from a specific url ./script/plugin install http://topfunky.net/svn/plugins/calendar_helper # Install by linking it directly within Subversion ./script/plugin install -x calendar_helper
If the script doesn’t automatically find the plugin, run the discovery action which looks for all the sources on the Rails wiki:
# Import new plugin sources ./script/plugin discover
There are also a few other arguments to the plugin script. Run ./script/plugin with no arguments to see all the options.
svn deletesvn propdel svn:externals vendor/plugins/Just like riding a bike or learning to swim, being able to write a plugin is a great skill. If you’ve written any Ruby code at all, you’re halfway there.
There are a few things that can only be done with a plugin (like writing your own generator). For the rest, you’ll appreciate the ability to share common code between your applications or with other developers.
Plugins can do almost anything that a Rails app can, plus a little more. Here’s a short summary of the kinds of things a plugin can do:
lib folder and you’ll be ready to go.mixin). Also quite easy.app/controllers directory. Intermediate difficulty..rake file into the tasks folder and you can reuse your tasks!public directory. Intermediate difficulty.You can see the basic layout of a plugin by running the standard plugin generator:
# Use the generator to make a transmogrifier plugin ./script/generate plugin transmogrifier create vendor/plugins/transmogrifier/lib create vendor/plugins/transmogrifier/tasks create vendor/plugins/transmogrifier/test create vendor/plugins/transmogrifier/README create vendor/plugins/transmogrifier/Rakefile create vendor/plugins/transmogrifier/init.rb create vendor/plugins/transmogrifier/install.rb create vendor/plugins/transmogrifier/lib/transmogrifier.rb create vendor/plugins/transmogrifier/tasks/transmogrifier_tasks.rake create vendor/plugins/transmogrifier/test/transmogrifier_test.rb
Here’s the basic folder structure:
transmogrifier |-- init.rb |-- install.rb |-- Rakefile |-- README |-- lib/ | |-- transmogrifier.rb |-- tasks/ | |-- transmogrifier_tasks.rake |-- test | |-- transmogrifier_test.rb
None of these files are necessary, but they each do different things. You might write a plugin that only has a tasks folder, or another that only has a lib folder. Here is what each piece does:
init.rb file..rake file here as you would in lib/tasks. It’s automatic…no other action is needed!Not mentioned:
rake rdoc task.Next week I’ll step through the basics of making a plugin from scratch!

Nice job. Just what the community needs and right when it needs it. You’ve done it again. :) Thanks.
Rob
Ah! I could’ve used this a week ago. Oh well, better late than never. And this is such a great start!
Mitch
Technically you can put controllers into your lib folder. They will get loaded, but it’s a messy way of doing things.
Yea,... though Rails will whine about missing helper rb file for your controller if its only in the plugin lib folder. Then your plugin has to copy an empty helper into the helper folder.. doh!
On every single one of my rails boxes (1 osx, 2 centos) i’m getting the following error at the end of discover…just not sure why?
script/plugin discover or scrip/plugin discover -l gives the same
(eval):3:in `each’: undefined method `[]’ for nil:NilClass (NoMethodError) from /usr/lib64/ruby/gems/1.8/gems/rails-1.1.2/lib/commands/plugin.rb:658:in `scrape’ from /usr/lib64/ruby/gems/1.8/gems/rails-1.1.2/lib/commands/plugin.rb:632:in `parse!’ from /usr/lib64/ruby/gems/1.8/gems/rails-1.1.2/lib/commands/plugin.rb:631:in `parse!’ from /usr/lib64/ruby/gems/1.8/gems/rails-1.1.2/lib/commands/plugin.rb:447:in `parse!’ from /usr/lib64/ruby/gems/1.8/gems/rails-1.1.2/lib/commands/plugin.rb:463:in `parse!’ from /usr/lib64/ruby/gems/1.8/gems/rails-1.1.2/lib/commands/plugin.rb:871 from /usr/lib64/site_ruby/1.8/rubygems/custom_require.rb:21:in `require’ from /usr/lib64/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/dependencies.rb:147:in `require’ from script/plugin:3
On that line, the plugin script is trying to open the address of the Rails wiki using open-uri, a standard Ruby library.
So it looks like it can’t open the url correctly. Suggestions:
ruby -ropen-uri -e "puts open('http://nubyonrails.com').readlines"Looking forward to the rest. Thanks once again.
Excellent, very useful writeup.
A good read, as always. You do realize this will only help fuel the ever exploding plethora of plugins?! :)
Great resource, Not enough info on plugins out there and this is a great start. Thanks Craig
If you want to add controllers/views to a plugin, you’re probably best off using engines
Thanks for part 1. Would there be any chance of detailing the rails way to write tests for your plugins, especially ones which require a database/fixtures.
Part II is now available.
Like most rails documentation, it is rich in examples and light on definitions. I think there is generation gap here. The documentation for a thing is a contract about what you can do with it.
What is needed is:
1) Rails reads the source at X time into Y module and the code and data become available to A, B and C.
2) Do or do not define globals, constants, classes, modules in the source of a plugin. Do or do not assume the database connection has already been made.
3) The plugin code can only be called during the time a user is connected or can be called at any time, which?
Stuff like that is documentation. This is email between friends. It ain’t the same.
Thanks for the feedback!
This was intentionally high-level to give a broader introduction to plugins. Part II goes into more detail. I’ll include some of the issues you mentioned in Part III.
Of course, a whole book would be written on the topic. It’s on my personal list but might not be completed until the end of the year.
A new plugin directory written by those wild and crazy guys at RadRails is now live.
There’s no search, but there will be an API. It also integrates with RadRails.
Who will be the first to write a TextMate plugin?
The rails plugin directory at http://www.agilewebdevelopment.com/plugins has an API, search, and tags. :)
Sigh … my first post to somewhere like this, so please be gentle ;-)
While I luv Ruby and Rails, my frustrations of the last couple of days began while trying to use SOAP and a Wsdl definition that requires Basic Authorisation.
A search led me to Chris McMahon’s Blog, which says that I need to intall net/http and the latest version of SOAP4R. I download the tars from the links, but I have no idea what to do with them (I’m on Windows).
I guess the downloads are plug-ins? Anyway, I find this site and read this article and I try:
ruby script/plugin install calendar_helper
and get:
ruby: No such file or directory—script/plugin
So, I must have done something dumb somewhere, but I’m feeling very lost about now.
Can you help?
regards
Mark
Both Net::HTTP and a basic SOAP library are built into Ruby.
Here are a few articles that might help:
To clarify, the plugin system mentioned here is specifically for Rails. For general Ruby libraries there is RubyGems.
This is good kick off for plugin un rails
Hi
Some one known how to install a plugin without internet?
I already downloaded all files from the snv repository.
Rick.
@rick: if you have the files then drop them into your vendor/plugins directory [ex: it will end up having files vendor/plugins/plugin_name and vendor/plugins/plugin_name/lib
Thanks for the good page! Answered my question. -R
ok said
Thanks buddy! its really helpful for beginners like me.
cool stuff really helped me :)