The Complete Guide to Rails Plugins: Part I 21 comments

posted Thursday, May 4, 2006 by topfunky

At 37signals we usually use five or six plugins in each app. — David Heinemeier Hansson at Canada on Rails

Using Plugins in Your App

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:

Discover and Install

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.

To uninstall a plugin, you can:
  • Delete the specific folder for the plugin
  • Remove it with svn delete
  • Unlink it with svn propdel svn:externals vendor/plugins/

Writing a Plugin

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.

Plugin-Man, Plugin-Man, Doing the Things a Plugin Can

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:

  • Models: This is the easiest kind of plugin to write. Drop a model in the plugin’s lib folder and you’ll be ready to go.
  • View Helpers: A helper method can be slurped into the rest of your app (the technical term is mixin). Also quite easy.
  • Controllers: You can’t directly write a controller plugin, but you can write a generator that copies a controller to your app/controllers directory. Intermediate difficulty.
  • rake Tasks: Better living through automation! Drop a .rake file into the tasks folder and you can reuse your tasks!
  • Images, Stylesheets, Javascripts: A generator can copy these into the public directory. Intermediate difficulty.
  • Test assertions: Can easily be mixed-in to your tests.
  • Unit and Functional tests: As with controllers, these can be generated. Intermediate difficulty.
  • Other functionality: There are plenty of other things you might want to do with your app: connect to a payment processor, send messages to the Basecamp API, use a Campfire bot, generate graphs, etc. These can be done easily with plugins.

Folder Layout

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: Runs everytime the Rails app is started. Useful for mixing-in a helper module so all your views can use it.
  • install.rb: Runs one time only when the plugin is first installed. Can be used to copy required files or to show installation instructions.
  • Rakefile: Generates documentation and runs tests for the plugin.
  • lib/: Contains actual Ruby code. New models and other libraries in this folder will be automatically available to your Rails app. Helpers can be included specially, using the init.rb file.
  • tasks/: Drop a .rake file here as you would in lib/tasks. It’s automatic…no other action is needed!
  • test/: Write tests to verify the operation of your plugin.

Not mentioned:

  • generators/: Used for passive code generation, like the built-in scaffolds.
  • rdoc/: Contains generated documentation from the rake rdoc task.
  • MIT-LICENSE: It helps to paste this, or your preferred license. There’s nothing stopping you from making a plugin and selling it commercially or just keeping it internally for your company. If you have proprietary business logic in your plugin, you probably don’t want to make it available to the public!

Next Time…

Next week I’ll step through the basics of making a plugin from scratch!

Other Resources

Ruby on Rails Workshops in New York City and San Francisco
21 comments

Leave a response

  • Gravatar icon Rob Orsini

    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

  • Gravatar icon James Adam

    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

  • Gravatar icon topfunky

    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:

    • Does /usr/local/lb/ruby/1.8/open-uri.rb exist?
    • Can you use open-uri otherwise? Try this one-liner:
    ruby -ropen-uri -e "puts open('http://nubyonrails.com').readlines" 
    

  • Gravatar icon Joshua Jarman

    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

  • Gravatar icon Pat

    If you want to add controllers/views to a plugin, you’re probably best off using engines

  • Gravatar icon Ian

    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.

  • Gravatar icon Warren

    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. :)

  • Gravatar icon Ratmeister

    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

  • Gravatar icon topfunky

    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

  • Gravatar icon Rick

    Hi

    Some one known how to install a plugin without internet?

    I already downloaded all files from the snv repository.

    Rick.

Your Comment

Nuby on Rails

Geoffrey Grosenbach / Ruby / Code / Graphics / Design / Rails / Merb / Javascript / CSS

Ads by The Lounge

Manufactured with

Subscribe

Subscribe (RSS)